diff --git a/1/000004.log b/1/000004.log deleted file mode 100644 index eb9ba11701504..0000000000000 Binary files a/1/000004.log and /dev/null differ diff --git a/1/CURRENT b/1/CURRENT deleted file mode 100644 index aa5bb8ea50905..0000000000000 --- a/1/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000005 diff --git a/1/IDENTITY b/1/IDENTITY deleted file mode 100644 index 159583a5b81c0..0000000000000 --- a/1/IDENTITY +++ /dev/null @@ -1 +0,0 @@ -8c9a47d2-f374-44fd-80f9-eefc0e28aa2a \ No newline at end of file diff --git a/1/LOCK b/1/LOCK deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/1/LOG b/1/LOG deleted file mode 100644 index 1d33d750026d9..0000000000000 --- a/1/LOG +++ /dev/null @@ -1,703 +0,0 @@ -2025/01/16-16:30:20.990780 8655993536 RocksDB version: 8.1.1 -2025/01/16-16:30:20.991266 8655993536 Compile date 2023-04-06 16:38:52 -2025/01/16-16:30:20.991268 8655993536 DB SUMMARY -2025/01/16-16:30:20.991268 8655993536 DB Session ID: YXI8G6YWQHZKPQJ9LUQ4 -2025/01/16-16:30:20.991312 8655993536 SST files in 1 dir, Total Num: 0, files: -2025/01/16-16:30:20.991313 8655993536 Write Ahead Log file in 1: -2025/01/16-16:30:20.991314 8655993536 Options.error_if_exists: 0 -2025/01/16-16:30:20.991314 8655993536 Options.create_if_missing: 1 -2025/01/16-16:30:20.991315 8655993536 Options.paranoid_checks: 1 -2025/01/16-16:30:20.991315 8655993536 Options.flush_verify_memtable_count: 1 -2025/01/16-16:30:20.991316 8655993536 Options.track_and_verify_wals_in_manifest: 0 -2025/01/16-16:30:20.991316 8655993536 Options.verify_sst_unique_id_in_manifest: 1 -2025/01/16-16:30:20.991316 8655993536 Options.env: 0x1040bd240 -2025/01/16-16:30:20.991317 8655993536 Options.fs: PosixFileSystem -2025/01/16-16:30:20.991317 8655993536 Options.info_log: 0x14d60a9d8 -2025/01/16-16:30:20.991318 8655993536 Options.max_file_opening_threads: 16 -2025/01/16-16:30:20.991318 8655993536 Options.statistics: 0x0 -2025/01/16-16:30:20.991318 8655993536 Options.use_fsync: 0 -2025/01/16-16:30:20.991319 8655993536 Options.max_log_file_size: 0 -2025/01/16-16:30:20.991319 8655993536 Options.max_manifest_file_size: 1073741824 -2025/01/16-16:30:20.991320 8655993536 Options.log_file_time_to_roll: 0 -2025/01/16-16:30:20.991320 8655993536 Options.keep_log_file_num: 1000 -2025/01/16-16:30:20.991320 8655993536 Options.recycle_log_file_num: 0 -2025/01/16-16:30:20.991321 8655993536 Options.allow_fallocate: 1 -2025/01/16-16:30:20.991321 8655993536 Options.allow_mmap_reads: 0 -2025/01/16-16:30:20.991321 8655993536 Options.allow_mmap_writes: 0 -2025/01/16-16:30:20.991322 8655993536 Options.use_direct_reads: 0 -2025/01/16-16:30:20.991322 8655993536 Options.use_direct_io_for_flush_and_compaction: 0 -2025/01/16-16:30:20.991322 8655993536 Options.create_missing_column_families: 1 -2025/01/16-16:30:20.991323 8655993536 Options.db_log_dir: -2025/01/16-16:30:20.991323 8655993536 Options.wal_dir: -2025/01/16-16:30:20.991324 8655993536 Options.table_cache_numshardbits: 10 -2025/01/16-16:30:20.991324 8655993536 Options.WAL_ttl_seconds: 0 -2025/01/16-16:30:20.991324 8655993536 Options.WAL_size_limit_MB: 0 -2025/01/16-16:30:20.991325 8655993536 Options.max_write_batch_group_size_bytes: 1048576 -2025/01/16-16:30:20.991325 8655993536 Options.manifest_preallocation_size: 4194304 -2025/01/16-16:30:20.991325 8655993536 Options.is_fd_close_on_exec: 1 -2025/01/16-16:30:20.991326 8655993536 Options.advise_random_on_open: 1 -2025/01/16-16:30:20.991326 8655993536 Options.db_write_buffer_size: 1073741824 -2025/01/16-16:30:20.991327 8655993536 Options.write_buffer_manager: 0x60000117c820 -2025/01/16-16:30:20.991327 8655993536 Options.access_hint_on_compaction_start: 1 -2025/01/16-16:30:20.991327 8655993536 Options.random_access_max_buffer_size: 1048576 -2025/01/16-16:30:20.991328 8655993536 Options.use_adaptive_mutex: 0 -2025/01/16-16:30:20.991328 8655993536 Options.rate_limiter: 0x0 -2025/01/16-16:30:20.991329 8655993536 Options.sst_file_manager.rate_bytes_per_sec: 0 -2025/01/16-16:30:20.991329 8655993536 Options.wal_recovery_mode: 2 -2025/01/16-16:30:20.991329 8655993536 Options.enable_thread_tracking: 0 -2025/01/16-16:30:20.991330 8655993536 Options.enable_pipelined_write: 1 -2025/01/16-16:30:20.991330 8655993536 Options.unordered_write: 0 -2025/01/16-16:30:20.991330 8655993536 Options.allow_concurrent_memtable_write: 1 -2025/01/16-16:30:20.991331 8655993536 Options.enable_write_thread_adaptive_yield: 1 -2025/01/16-16:30:20.991331 8655993536 Options.write_thread_max_yield_usec: 100 -2025/01/16-16:30:20.991331 8655993536 Options.write_thread_slow_yield_usec: 3 -2025/01/16-16:30:20.991332 8655993536 Options.row_cache: None -2025/01/16-16:30:20.991332 8655993536 Options.wal_filter: None -2025/01/16-16:30:20.991333 8655993536 Options.avoid_flush_during_recovery: 0 -2025/01/16-16:30:20.991333 8655993536 Options.allow_ingest_behind: 0 -2025/01/16-16:30:20.991333 8655993536 Options.two_write_queues: 0 -2025/01/16-16:30:20.991334 8655993536 Options.manual_wal_flush: 0 -2025/01/16-16:30:20.991334 8655993536 Options.wal_compression: 0 -2025/01/16-16:30:20.991335 8655993536 Options.atomic_flush: 0 -2025/01/16-16:30:20.991335 8655993536 Options.avoid_unnecessary_blocking_io: 0 -2025/01/16-16:30:20.991335 8655993536 Options.persist_stats_to_disk: 0 -2025/01/16-16:30:20.991336 8655993536 Options.write_dbid_to_manifest: 0 -2025/01/16-16:30:20.991336 8655993536 Options.log_readahead_size: 0 -2025/01/16-16:30:20.991337 8655993536 Options.file_checksum_gen_factory: Unknown -2025/01/16-16:30:20.991337 8655993536 Options.best_efforts_recovery: 0 -2025/01/16-16:30:20.991337 8655993536 Options.max_bgerror_resume_count: 2147483647 -2025/01/16-16:30:20.991338 8655993536 Options.bgerror_resume_retry_interval: 1000000 -2025/01/16-16:30:20.991338 8655993536 Options.allow_data_in_errors: 0 -2025/01/16-16:30:20.991338 8655993536 Options.db_host_id: __hostname__ -2025/01/16-16:30:20.991339 8655993536 Options.enforce_single_del_contracts: true -2025/01/16-16:30:20.991339 8655993536 Options.max_background_jobs: 8 -2025/01/16-16:30:20.991340 8655993536 Options.max_background_compactions: -1 -2025/01/16-16:30:20.991340 8655993536 Options.max_subcompactions: 1 -2025/01/16-16:30:20.991340 8655993536 Options.avoid_flush_during_shutdown: 0 -2025/01/16-16:30:20.991341 8655993536 Options.writable_file_max_buffer_size: 1048576 -2025/01/16-16:30:20.991341 8655993536 Options.delayed_write_rate : 16777216 -2025/01/16-16:30:20.991342 8655993536 Options.max_total_wal_size: 1073741824 -2025/01/16-16:30:20.991342 8655993536 Options.delete_obsolete_files_period_micros: 21600000000 -2025/01/16-16:30:20.991342 8655993536 Options.stats_dump_period_sec: 600 -2025/01/16-16:30:20.991343 8655993536 Options.stats_persist_period_sec: 600 -2025/01/16-16:30:20.991343 8655993536 Options.stats_history_buffer_size: 1048576 -2025/01/16-16:30:20.991344 8655993536 Options.max_open_files: 11520 -2025/01/16-16:30:20.991344 8655993536 Options.bytes_per_sync: 0 -2025/01/16-16:30:20.991344 8655993536 Options.wal_bytes_per_sync: 0 -2025/01/16-16:30:20.991345 8655993536 Options.strict_bytes_per_sync: 0 -2025/01/16-16:30:20.991345 8655993536 Options.compaction_readahead_size: 0 -2025/01/16-16:30:20.991345 8655993536 Options.max_background_flushes: -1 -2025/01/16-16:30:20.991346 8655993536 Compression algorithms supported: -2025/01/16-16:30:20.991375 8655993536 kZSTD supported: 1 -2025/01/16-16:30:20.991375 8655993536 kZlibCompression supported: 1 -2025/01/16-16:30:20.991376 8655993536 kXpressCompression supported: 0 -2025/01/16-16:30:20.991376 8655993536 kSnappyCompression supported: 1 -2025/01/16-16:30:20.991376 8655993536 kZSTDNotFinalCompression supported: 1 -2025/01/16-16:30:20.991377 8655993536 kLZ4HCCompression supported: 1 -2025/01/16-16:30:20.991377 8655993536 kLZ4Compression supported: 1 -2025/01/16-16:30:20.991377 8655993536 kBZip2Compression supported: 0 -2025/01/16-16:30:20.991382 8655993536 Fast CRC32 supported: Supported on Arm64 -2025/01/16-16:30:20.991382 8655993536 DMutex implementation: pthread_mutex_t -2025/01/16-16:30:20.991882 8655993536 [db/db_impl/db_impl_open.cc:315] Creating manifest 1 -2025/01/16-16:30:20.992179 8655993536 [db/version_set.cc:5662] Recovering from manifest file: 1/MANIFEST-000001 -2025/01/16-16:30:20.992248 8655993536 [db/column_family.cc:621] --------------- Options for column family [default]: -2025/01/16-16:30:20.992249 8655993536 Options.comparator: leveldb.BytewiseComparator -2025/01/16-16:30:20.992250 8655993536 Options.merge_operator: None -2025/01/16-16:30:20.992250 8655993536 Options.compaction_filter: None -2025/01/16-16:30:20.992250 8655993536 Options.compaction_filter_factory: None -2025/01/16-16:30:20.992251 8655993536 Options.sst_partitioner_factory: None -2025/01/16-16:30:20.992251 8655993536 Options.memtable_factory: SkipListFactory -2025/01/16-16:30:20.992252 8655993536 Options.table_factory: BlockBasedTable -2025/01/16-16:30:20.992259 8655993536 table_factory options: flush_block_policy_factory: FlushBlockBySizePolicyFactory (0x600002a7a7c0) - cache_index_and_filter_blocks: 0 - cache_index_and_filter_blocks_with_high_priority: 1 - pin_l0_filter_and_index_blocks_in_cache: 0 - pin_top_level_index_and_filter: 1 - index_type: 0 - data_block_index_type: 0 - index_shortening: 1 - data_block_hash_table_util_ratio: 0.750000 - checksum: 4 - no_block_cache: 0 - block_cache: 0x600001f7c918 - block_cache_name: LRUCache - block_cache_options: - capacity : 8388608 - num_shard_bits : 4 - strict_capacity_limit : 0 - memory_allocator : None - high_pri_pool_ratio: 0.000 - low_pri_pool_ratio: 0.000 - persistent_cache: 0x0 - block_size: 4096 - block_size_deviation: 10 - block_restart_interval: 16 - index_block_restart_interval: 1 - metadata_block_size: 4096 - partition_filters: 0 - use_delta_encoding: 1 - filter_policy: nullptr - whole_key_filtering: 1 - verify_compression: 0 - read_amp_bytes_per_bit: 0 - format_version: 5 - enable_index_compression: 1 - block_align: 0 - max_auto_readahead_size: 262144 - prepopulate_block_cache: 0 - initial_auto_readahead_size: 8192 - num_file_reads_for_auto_readahead: 2 -2025/01/16-16:30:20.992260 8655993536 Options.write_buffer_size: 67108864 -2025/01/16-16:30:20.992261 8655993536 Options.max_write_buffer_number: 2 -2025/01/16-16:30:20.992261 8655993536 Options.compression: Snappy -2025/01/16-16:30:20.992262 8655993536 Options.bottommost_compression: Disabled -2025/01/16-16:30:20.992262 8655993536 Options.prefix_extractor: nullptr -2025/01/16-16:30:20.992263 8655993536 Options.memtable_insert_with_hint_prefix_extractor: nullptr -2025/01/16-16:30:20.992263 8655993536 Options.num_levels: 7 -2025/01/16-16:30:20.992263 8655993536 Options.min_write_buffer_number_to_merge: 1 -2025/01/16-16:30:20.992264 8655993536 Options.max_write_buffer_number_to_maintain: 0 -2025/01/16-16:30:20.992264 8655993536 Options.max_write_buffer_size_to_maintain: 0 -2025/01/16-16:30:20.992264 8655993536 Options.bottommost_compression_opts.window_bits: -14 -2025/01/16-16:30:20.992265 8655993536 Options.bottommost_compression_opts.level: 32767 -2025/01/16-16:30:20.992265 8655993536 Options.bottommost_compression_opts.strategy: 0 -2025/01/16-16:30:20.992266 8655993536 Options.bottommost_compression_opts.max_dict_bytes: 0 -2025/01/16-16:30:20.992266 8655993536 Options.bottommost_compression_opts.zstd_max_train_bytes: 0 -2025/01/16-16:30:20.992266 8655993536 Options.bottommost_compression_opts.parallel_threads: 1 -2025/01/16-16:30:20.992267 8655993536 Options.bottommost_compression_opts.enabled: false -2025/01/16-16:30:20.992267 8655993536 Options.bottommost_compression_opts.max_dict_buffer_bytes: 0 -2025/01/16-16:30:20.992268 8655993536 Options.bottommost_compression_opts.use_zstd_dict_trainer: true -2025/01/16-16:30:20.992268 8655993536 Options.compression_opts.window_bits: -14 -2025/01/16-16:30:20.992268 8655993536 Options.compression_opts.level: 32767 -2025/01/16-16:30:20.992269 8655993536 Options.compression_opts.strategy: 0 -2025/01/16-16:30:20.992269 8655993536 Options.compression_opts.max_dict_bytes: 0 -2025/01/16-16:30:20.992269 8655993536 Options.compression_opts.zstd_max_train_bytes: 0 -2025/01/16-16:30:20.992270 8655993536 Options.compression_opts.use_zstd_dict_trainer: true -2025/01/16-16:30:20.992270 8655993536 Options.compression_opts.parallel_threads: 1 -2025/01/16-16:30:20.992270 8655993536 Options.compression_opts.enabled: false -2025/01/16-16:30:20.992271 8655993536 Options.compression_opts.max_dict_buffer_bytes: 0 -2025/01/16-16:30:20.992271 8655993536 Options.level0_file_num_compaction_trigger: 4 -2025/01/16-16:30:20.992272 8655993536 Options.level0_slowdown_writes_trigger: 20 -2025/01/16-16:30:20.992272 8655993536 Options.level0_stop_writes_trigger: 36 -2025/01/16-16:30:20.992272 8655993536 Options.target_file_size_base: 67108864 -2025/01/16-16:30:20.992273 8655993536 Options.target_file_size_multiplier: 1 -2025/01/16-16:30:20.992273 8655993536 Options.max_bytes_for_level_base: 268435456 -2025/01/16-16:30:20.992273 8655993536 Options.level_compaction_dynamic_level_bytes: 0 -2025/01/16-16:30:20.992274 8655993536 Options.max_bytes_for_level_multiplier: 10.000000 -2025/01/16-16:30:20.992274 8655993536 Options.max_bytes_for_level_multiplier_addtl[0]: 1 -2025/01/16-16:30:20.992275 8655993536 Options.max_bytes_for_level_multiplier_addtl[1]: 1 -2025/01/16-16:30:20.992275 8655993536 Options.max_bytes_for_level_multiplier_addtl[2]: 1 -2025/01/16-16:30:20.992276 8655993536 Options.max_bytes_for_level_multiplier_addtl[3]: 1 -2025/01/16-16:30:20.992276 8655993536 Options.max_bytes_for_level_multiplier_addtl[4]: 1 -2025/01/16-16:30:20.992276 8655993536 Options.max_bytes_for_level_multiplier_addtl[5]: 1 -2025/01/16-16:30:20.992277 8655993536 Options.max_bytes_for_level_multiplier_addtl[6]: 1 -2025/01/16-16:30:20.992277 8655993536 Options.max_sequential_skip_in_iterations: 8 -2025/01/16-16:30:20.992277 8655993536 Options.max_compaction_bytes: 1677721600 -2025/01/16-16:30:20.992278 8655993536 Options.ignore_max_compaction_bytes_for_input: true -2025/01/16-16:30:20.992278 8655993536 Options.arena_block_size: 1048576 -2025/01/16-16:30:20.992279 8655993536 Options.soft_pending_compaction_bytes_limit: 68719476736 -2025/01/16-16:30:20.992279 8655993536 Options.hard_pending_compaction_bytes_limit: 274877906944 -2025/01/16-16:30:20.992279 8655993536 Options.disable_auto_compactions: 0 -2025/01/16-16:30:20.992280 8655993536 Options.compaction_style: kCompactionStyleLevel -2025/01/16-16:30:20.992280 8655993536 Options.compaction_pri: kMinOverlappingRatio -2025/01/16-16:30:20.992281 8655993536 Options.compaction_options_universal.size_ratio: 1 -2025/01/16-16:30:20.992281 8655993536 Options.compaction_options_universal.min_merge_width: 2 -2025/01/16-16:30:20.992281 8655993536 Options.compaction_options_universal.max_merge_width: 4294967295 -2025/01/16-16:30:20.992282 8655993536 Options.compaction_options_universal.max_size_amplification_percent: 200 -2025/01/16-16:30:20.992282 8655993536 Options.compaction_options_universal.compression_size_percent: -1 -2025/01/16-16:30:20.992283 8655993536 Options.compaction_options_universal.stop_style: kCompactionStopStyleTotalSize -2025/01/16-16:30:20.992283 8655993536 Options.compaction_options_fifo.max_table_files_size: 1073741824 -2025/01/16-16:30:20.992283 8655993536 Options.compaction_options_fifo.allow_compaction: 0 -2025/01/16-16:30:20.992285 8655993536 Options.table_properties_collectors: -2025/01/16-16:30:20.992285 8655993536 Options.inplace_update_support: 0 -2025/01/16-16:30:20.992286 8655993536 Options.inplace_update_num_locks: 10000 -2025/01/16-16:30:20.992286 8655993536 Options.memtable_prefix_bloom_size_ratio: 0.000000 -2025/01/16-16:30:20.992286 8655993536 Options.memtable_whole_key_filtering: 0 -2025/01/16-16:30:20.992287 8655993536 Options.memtable_huge_page_size: 0 -2025/01/16-16:30:20.992287 8655993536 Options.bloom_locality: 0 -2025/01/16-16:30:20.992288 8655993536 Options.max_successive_merges: 0 -2025/01/16-16:30:20.992288 8655993536 Options.optimize_filters_for_hits: 0 -2025/01/16-16:30:20.992288 8655993536 Options.paranoid_file_checks: 0 -2025/01/16-16:30:20.992289 8655993536 Options.force_consistency_checks: 1 -2025/01/16-16:30:20.992289 8655993536 Options.report_bg_io_stats: 0 -2025/01/16-16:30:20.992289 8655993536 Options.ttl: 2592000 -2025/01/16-16:30:20.992290 8655993536 Options.periodic_compaction_seconds: 0 -2025/01/16-16:30:20.992290 8655993536 Options.preclude_last_level_data_seconds: 0 -2025/01/16-16:30:20.992290 8655993536 Options.preserve_internal_time_seconds: 0 -2025/01/16-16:30:20.992291 8655993536 Options.enable_blob_files: false -2025/01/16-16:30:20.992291 8655993536 Options.min_blob_size: 0 -2025/01/16-16:30:20.992292 8655993536 Options.blob_file_size: 268435456 -2025/01/16-16:30:20.992292 8655993536 Options.blob_compression_type: NoCompression -2025/01/16-16:30:20.992292 8655993536 Options.enable_blob_garbage_collection: false -2025/01/16-16:30:20.992293 8655993536 Options.blob_garbage_collection_age_cutoff: 0.250000 -2025/01/16-16:30:20.992293 8655993536 Options.blob_garbage_collection_force_threshold: 1.000000 -2025/01/16-16:30:20.992294 8655993536 Options.blob_compaction_readahead_size: 0 -2025/01/16-16:30:20.992294 8655993536 Options.blob_file_starting_level: 0 -2025/01/16-16:30:20.992294 8655993536 Options.experimental_mempurge_threshold: 0.000000 -2025/01/16-16:30:20.992658 8655993536 [db/version_set.cc:5713] Recovered from manifest file:1/MANIFEST-000001 succeeded,manifest_file_number is 1, next_file_number is 3, last_sequence is 0, log_number is 0,prev_log_number is 0,max_column_family is 0,min_log_number_to_keep is 0 -2025/01/16-16:30:20.992659 8655993536 [db/version_set.cc:5722] Column family [default] (ID 0), log number is 0 -2025/01/16-16:30:20.992698 8655993536 [db/db_impl/db_impl_open.cc:537] DB ID: 8c9a47d2-f374-44fd-80f9-eefc0e28aa2a -2025/01/16-16:30:20.992883 8655993536 [db/version_set.cc:5180] Creating manifest 5 -2025/01/16-16:30:20.993256 8655993536 [db/column_family.cc:621] --------------- Options for column family [log]: -2025/01/16-16:30:20.993258 8655993536 Options.comparator: leveldb.BytewiseComparator -2025/01/16-16:30:20.993259 8655993536 Options.merge_operator: None -2025/01/16-16:30:20.993259 8655993536 Options.compaction_filter: None -2025/01/16-16:30:20.993260 8655993536 Options.compaction_filter_factory: None -2025/01/16-16:30:20.993260 8655993536 Options.sst_partitioner_factory: None -2025/01/16-16:30:20.993261 8655993536 Options.memtable_factory: SkipListFactory -2025/01/16-16:30:20.993261 8655993536 Options.table_factory: BlockBasedTable -2025/01/16-16:30:20.993296 8655993536 table_factory options: flush_block_policy_factory: FlushBlockBySizePolicyFactory (0x600002a7a740) - cache_index_and_filter_blocks: 0 - cache_index_and_filter_blocks_with_high_priority: 1 - pin_l0_filter_and_index_blocks_in_cache: 1 - pin_top_level_index_and_filter: 1 - index_type: 0 - data_block_index_type: 0 - index_shortening: 1 - data_block_hash_table_util_ratio: 0.750000 - checksum: 4 - no_block_cache: 0 - block_cache: 0x600001f7c9d8 - block_cache_name: LRUCache - block_cache_options: - capacity : 134217728 - num_shard_bits : 6 - strict_capacity_limit : 0 - memory_allocator : None - high_pri_pool_ratio: 0.500 - low_pri_pool_ratio: 0.000 - persistent_cache: 0x0 - block_size: 16384 - block_size_deviation: 10 - block_restart_interval: 16 - index_block_restart_interval: 1 - metadata_block_size: 4096 - partition_filters: 0 - use_delta_encoding: 1 - filter_policy: bloomfilter - whole_key_filtering: 1 - verify_compression: 0 - read_amp_bytes_per_bit: 0 - format_version: 5 - enable_index_compression: 1 - block_align: 0 - max_auto_readahead_size: 262144 - prepopulate_block_cache: 0 - initial_auto_readahead_size: 8192 - num_file_reads_for_auto_readahead: 2 -2025/01/16-16:30:20.993297 8655993536 Options.write_buffer_size: 67108864 -2025/01/16-16:30:20.993298 8655993536 Options.max_write_buffer_number: 2 -2025/01/16-16:30:20.993298 8655993536 Options.compression: LZ4 -2025/01/16-16:30:20.993299 8655993536 Options.bottommost_compression: ZSTD -2025/01/16-16:30:20.993299 8655993536 Options.prefix_extractor: nullptr -2025/01/16-16:30:20.993299 8655993536 Options.memtable_insert_with_hint_prefix_extractor: nullptr -2025/01/16-16:30:20.993300 8655993536 Options.num_levels: 7 -2025/01/16-16:30:20.993300 8655993536 Options.min_write_buffer_number_to_merge: 1 -2025/01/16-16:30:20.993301 8655993536 Options.max_write_buffer_number_to_maintain: 0 -2025/01/16-16:30:20.993301 8655993536 Options.max_write_buffer_size_to_maintain: 0 -2025/01/16-16:30:20.993301 8655993536 Options.bottommost_compression_opts.window_bits: -14 -2025/01/16-16:30:20.993302 8655993536 Options.bottommost_compression_opts.level: 32767 -2025/01/16-16:30:20.993302 8655993536 Options.bottommost_compression_opts.strategy: 0 -2025/01/16-16:30:20.993303 8655993536 Options.bottommost_compression_opts.max_dict_bytes: 0 -2025/01/16-16:30:20.993303 8655993536 Options.bottommost_compression_opts.zstd_max_train_bytes: 1048576 -2025/01/16-16:30:20.993303 8655993536 Options.bottommost_compression_opts.parallel_threads: 1 -2025/01/16-16:30:20.993304 8655993536 Options.bottommost_compression_opts.enabled: true -2025/01/16-16:30:20.993304 8655993536 Options.bottommost_compression_opts.max_dict_buffer_bytes: 0 -2025/01/16-16:30:20.993305 8655993536 Options.bottommost_compression_opts.use_zstd_dict_trainer: true -2025/01/16-16:30:20.993305 8655993536 Options.compression_opts.window_bits: -14 -2025/01/16-16:30:20.993305 8655993536 Options.compression_opts.level: 32767 -2025/01/16-16:30:20.993306 8655993536 Options.compression_opts.strategy: 0 -2025/01/16-16:30:20.993306 8655993536 Options.compression_opts.max_dict_bytes: 0 -2025/01/16-16:30:20.993307 8655993536 Options.compression_opts.zstd_max_train_bytes: 0 -2025/01/16-16:30:20.993307 8655993536 Options.compression_opts.use_zstd_dict_trainer: true -2025/01/16-16:30:20.993307 8655993536 Options.compression_opts.parallel_threads: 1 -2025/01/16-16:30:20.993308 8655993536 Options.compression_opts.enabled: false -2025/01/16-16:30:20.993308 8655993536 Options.compression_opts.max_dict_buffer_bytes: 0 -2025/01/16-16:30:20.993309 8655993536 Options.level0_file_num_compaction_trigger: 4 -2025/01/16-16:30:20.993309 8655993536 Options.level0_slowdown_writes_trigger: 20 -2025/01/16-16:30:20.993309 8655993536 Options.level0_stop_writes_trigger: 36 -2025/01/16-16:30:20.993310 8655993536 Options.target_file_size_base: 67108864 -2025/01/16-16:30:20.993310 8655993536 Options.target_file_size_multiplier: 1 -2025/01/16-16:30:20.993310 8655993536 Options.max_bytes_for_level_base: 268435456 -2025/01/16-16:30:20.993311 8655993536 Options.level_compaction_dynamic_level_bytes: 0 -2025/01/16-16:30:20.993311 8655993536 Options.max_bytes_for_level_multiplier: 10.000000 -2025/01/16-16:30:20.993312 8655993536 Options.max_bytes_for_level_multiplier_addtl[0]: 1 -2025/01/16-16:30:20.993312 8655993536 Options.max_bytes_for_level_multiplier_addtl[1]: 1 -2025/01/16-16:30:20.993313 8655993536 Options.max_bytes_for_level_multiplier_addtl[2]: 1 -2025/01/16-16:30:20.993313 8655993536 Options.max_bytes_for_level_multiplier_addtl[3]: 1 -2025/01/16-16:30:20.993313 8655993536 Options.max_bytes_for_level_multiplier_addtl[4]: 1 -2025/01/16-16:30:20.993314 8655993536 Options.max_bytes_for_level_multiplier_addtl[5]: 1 -2025/01/16-16:30:20.993314 8655993536 Options.max_bytes_for_level_multiplier_addtl[6]: 1 -2025/01/16-16:30:20.993314 8655993536 Options.max_sequential_skip_in_iterations: 8 -2025/01/16-16:30:20.993315 8655993536 Options.max_compaction_bytes: 1677721600 -2025/01/16-16:30:20.993315 8655993536 Options.ignore_max_compaction_bytes_for_input: true -2025/01/16-16:30:20.993316 8655993536 Options.arena_block_size: 1048576 -2025/01/16-16:30:20.993316 8655993536 Options.soft_pending_compaction_bytes_limit: 68719476736 -2025/01/16-16:30:20.993316 8655993536 Options.hard_pending_compaction_bytes_limit: 274877906944 -2025/01/16-16:30:20.993317 8655993536 Options.disable_auto_compactions: 0 -2025/01/16-16:30:20.993317 8655993536 Options.compaction_style: kCompactionStyleLevel -2025/01/16-16:30:20.993318 8655993536 Options.compaction_pri: kMinOverlappingRatio -2025/01/16-16:30:20.993318 8655993536 Options.compaction_options_universal.size_ratio: 1 -2025/01/16-16:30:20.993318 8655993536 Options.compaction_options_universal.min_merge_width: 2 -2025/01/16-16:30:20.993319 8655993536 Options.compaction_options_universal.max_merge_width: 4294967295 -2025/01/16-16:30:20.993319 8655993536 Options.compaction_options_universal.max_size_amplification_percent: 200 -2025/01/16-16:30:20.993320 8655993536 Options.compaction_options_universal.compression_size_percent: -1 -2025/01/16-16:30:20.993320 8655993536 Options.compaction_options_universal.stop_style: kCompactionStopStyleTotalSize -2025/01/16-16:30:20.993320 8655993536 Options.compaction_options_fifo.max_table_files_size: 1073741824 -2025/01/16-16:30:20.993321 8655993536 Options.compaction_options_fifo.allow_compaction: 0 -2025/01/16-16:30:20.993321 8655993536 Options.table_properties_collectors: -2025/01/16-16:30:20.993322 8655993536 Options.inplace_update_support: 0 -2025/01/16-16:30:20.993322 8655993536 Options.inplace_update_num_locks: 10000 -2025/01/16-16:30:20.993322 8655993536 Options.memtable_prefix_bloom_size_ratio: 0.020000 -2025/01/16-16:30:20.993323 8655993536 Options.memtable_whole_key_filtering: 0 -2025/01/16-16:30:20.993323 8655993536 Options.memtable_huge_page_size: 0 -2025/01/16-16:30:20.993324 8655993536 Options.bloom_locality: 0 -2025/01/16-16:30:20.993324 8655993536 Options.max_successive_merges: 0 -2025/01/16-16:30:20.993324 8655993536 Options.optimize_filters_for_hits: 0 -2025/01/16-16:30:20.993325 8655993536 Options.paranoid_file_checks: 0 -2025/01/16-16:30:20.993325 8655993536 Options.force_consistency_checks: 1 -2025/01/16-16:30:20.993326 8655993536 Options.report_bg_io_stats: 0 -2025/01/16-16:30:20.993326 8655993536 Options.ttl: 2592000 -2025/01/16-16:30:20.993326 8655993536 Options.periodic_compaction_seconds: 0 -2025/01/16-16:30:20.993327 8655993536 Options.preclude_last_level_data_seconds: 0 -2025/01/16-16:30:20.993327 8655993536 Options.preserve_internal_time_seconds: 0 -2025/01/16-16:30:20.993327 8655993536 Options.enable_blob_files: false -2025/01/16-16:30:20.993328 8655993536 Options.min_blob_size: 0 -2025/01/16-16:30:20.993328 8655993536 Options.blob_file_size: 268435456 -2025/01/16-16:30:20.993329 8655993536 Options.blob_compression_type: NoCompression -2025/01/16-16:30:20.993329 8655993536 Options.enable_blob_garbage_collection: false -2025/01/16-16:30:20.993329 8655993536 Options.blob_garbage_collection_age_cutoff: 0.250000 -2025/01/16-16:30:20.993330 8655993536 Options.blob_garbage_collection_force_threshold: 1.000000 -2025/01/16-16:30:20.993330 8655993536 Options.blob_compaction_readahead_size: 0 -2025/01/16-16:30:20.993331 8655993536 Options.blob_file_starting_level: 0 -2025/01/16-16:30:20.993331 8655993536 Options.experimental_mempurge_threshold: 0.000000 -2025/01/16-16:30:20.993388 8655993536 [db/db_impl/db_impl.cc:3200] Created column family [log] (ID 1) -2025/01/16-16:30:20.994759 8655993536 [db/db_impl/db_impl_open.cc:1977] SstFileManager instance 0x14d60ace0 -2025/01/16-16:30:20.994773 8655993536 DB pointer 0x14d853a00 -2025/01/16-16:30:20.994912 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-16:30:20.994915 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 0.0 total, 0.0 interval -Cumulative writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -** Compaction Stats [default] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [default] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 0.0 total, 0.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c918#5595 capacity: 8.00 MB usage: 0.08 KB table_size: 256 occupancy: 87 collections: 1 last_copies: 0 last_secs: 6e-06 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [default] ** - -** Compaction Stats [log] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [log] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 0.0 total, 0.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c9d8#5595 capacity: 128.00 MB usage: 0.08 KB table_size: 1024 occupancy: 87 collections: 1 last_copies: 0 last_secs: 9e-06 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [log] ** -2025/01/16-16:40:21.000016 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-16:40:21.000759 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 600.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -** Compaction Stats [default] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [default] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 600.0 total, 600.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c918#5595 capacity: 8.00 MB usage: 0.08 KB table_size: 256 occupancy: 87 collections: 2 last_copies: 0 last_secs: 2.5e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [default] ** - -** Compaction Stats [log] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [log] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 600.0 total, 600.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c9d8#5595 capacity: 128.00 MB usage: 0.08 KB table_size: 1024 occupancy: 87 collections: 2 last_copies: 0 last_secs: 1.6e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [log] ** -2025/01/16-16:50:21.004712 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-16:50:21.005898 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 1200.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -** Compaction Stats [default] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [default] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 1200.0 total, 600.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c918#5595 capacity: 8.00 MB usage: 0.08 KB table_size: 256 occupancy: 87 collections: 3 last_copies: 0 last_secs: 3.8e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [default] ** - -** Compaction Stats [log] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [log] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 1200.0 total, 600.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c9d8#5595 capacity: 128.00 MB usage: 0.08 KB table_size: 1024 occupancy: 87 collections: 3 last_copies: 0 last_secs: 1.9e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [log] ** -2025/01/16-17:00:21.011040 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:00:21.011062 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 1800.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-17:10:21.015974 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:10:21.016021 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 2400.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-17:20:21.019238 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:20:21.020595 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 3000.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-17:30:21.023253 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:30:21.023288 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 3600.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-17:40:21.028505 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:40:21.028557 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 4200.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-17:50:21.031968 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-17:50:21.032044 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 4800.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-18:00:21.042025 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-18:00:21.043181 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 5400.0 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -2025/01/16-18:10:21.044952 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-18:10:21.046197 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 6000.1 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, -** Compaction Stats [default] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [default] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 6000.1 total, 4800.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c918#5595 capacity: 8.00 MB usage: 0.08 KB table_size: 256 occupancy: 87 collections: 11 last_copies: 0 last_secs: 5.6e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [default] ** - -** Compaction Stats [log] ** -Level Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sum 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - Int 0/0 0.00 KB 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.00 0.00 0 0.000 0 0 0.0 0.0 - -** Compaction Stats [log] ** -Priority Files Size Score Read(GB) Rn(GB) Rnp1(GB) Write(GB) Wnew(GB) Moved(GB) W-Amp Rd(MB/s) Wr(MB/s) Comp(sec) CompMergeCPU(sec) Comp(cnt) Avg(sec) KeyIn KeyDrop Rblob(GB) Wblob(GB) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -Blob file count: 0, total size: 0.0 GB, garbage size: 0.0 GB, space amp: 0.0 - -Uptime(secs): 6000.1 total, 4800.0 interval -Flush(GB): cumulative 0.000, interval 0.000 -AddFile(GB): cumulative 0.000, interval 0.000 -AddFile(Total Files): cumulative 0, interval 0 -AddFile(L0 Files): cumulative 0, interval 0 -AddFile(Keys): cumulative 0, interval 0 -Cumulative compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds -Write Stall (count): cf-l0-file-count-limit-delays-with-ongoing-compaction: 0, cf-l0-file-count-limit-stops-with-ongoing-compaction: 0, l0-file-count-limit-delays: 0, l0-file-count-limit-stops: 0, memtable-limit-delays: 0, memtable-limit-stops: 0, pending-compaction-bytes-delays: 0, pending-compaction-bytes-stops: 0, total-delays: 0, total-stops: 0, Block cache LRUCache@0x600001f7c9d8#5595 capacity: 128.00 MB usage: 0.08 KB table_size: 1024 occupancy: 87 collections: 11 last_copies: 0 last_secs: 3.3e-05 secs_since: 0 -Block cache entry stats(count,size,portion): Misc(1,0.00 KB,0%) - -** File Read Latency Histogram By Level [log] ** -2025/01/16-18:20:21.049845 6162395136 [db/db_impl/db_impl.cc:1085] ------- DUMPING STATS ------- -2025/01/16-18:20:21.051162 6162395136 [db/db_impl/db_impl.cc:1086] -** DB Stats ** -Uptime(secs): 6600.1 total, 600.0 interval -Cumulative writes: 2 writes, 2 keys, 2 commit groups, 1.0 writes per commit group, ingest: 0.00 GB, 0.00 MB/s -Cumulative WAL: 2 writes, 0 syncs, 2.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Cumulative stall: 00:00:0.000 H:M:S, 0.0 percent -Interval writes: 0 writes, 0 keys, 0 commit groups, 0.0 writes per commit group, ingest: 0.00 MB, 0.00 MB/s -Interval WAL: 0 writes, 0 syncs, 0.00 writes per sync, written: 0.00 GB, 0.00 MB/s -Interval stall: 00:00:0.000 H:M:S, 0.0 percent -Write Stall (count): write-buffer-manager-limit-stops: 0, diff --git a/1/MANIFEST-000005 b/1/MANIFEST-000005 deleted file mode 100644 index 097dfb05cc8d3..0000000000000 Binary files a/1/MANIFEST-000005 and /dev/null differ diff --git a/1/OPTIONS-000007 b/1/OPTIONS-000007 deleted file mode 100644 index 82283a0b5b7f1..0000000000000 --- a/1/OPTIONS-000007 +++ /dev/null @@ -1,304 +0,0 @@ -# This is a RocksDB option file. -# -# For detailed file format spec, please refer to the example file -# in examples/rocksdb_option_file_example.ini -# - -[Version] - rocksdb_version=8.1.1 - options_file_version=1.1 - -[DBOptions] - max_background_flushes=-1 - compaction_readahead_size=0 - strict_bytes_per_sync=false - wal_bytes_per_sync=0 - max_open_files=11520 - stats_history_buffer_size=1048576 - max_total_wal_size=1073741824 - stats_persist_period_sec=600 - stats_dump_period_sec=600 - avoid_flush_during_shutdown=false - max_subcompactions=1 - bytes_per_sync=0 - delayed_write_rate=16777216 - max_background_compactions=-1 - max_background_jobs=8 - delete_obsolete_files_period_micros=21600000000 - writable_file_max_buffer_size=1048576 - file_checksum_gen_factory=nullptr - allow_data_in_errors=false - max_bgerror_resume_count=2147483647 - best_efforts_recovery=false - write_dbid_to_manifest=false - atomic_flush=false - wal_compression=kNoCompression - manual_wal_flush=false - two_write_queues=false - avoid_flush_during_recovery=false - dump_malloc_stats=false - info_log_level=INFO_LEVEL - write_thread_slow_yield_usec=3 - allow_ingest_behind=false - fail_if_options_file_error=false - persist_stats_to_disk=false - WAL_ttl_seconds=0 - bgerror_resume_retry_interval=1000000 - allow_concurrent_memtable_write=true - paranoid_checks=true - WAL_size_limit_MB=0 - lowest_used_cache_tier=kNonVolatileBlockTier - keep_log_file_num=1000 - table_cache_numshardbits=10 - max_file_opening_threads=16 - use_fsync=false - unordered_write=false - random_access_max_buffer_size=1048576 - log_readahead_size=0 - enable_pipelined_write=true - wal_recovery_mode=kPointInTimeRecovery - db_write_buffer_size=1073741824 - allow_2pc=false - skip_checking_sst_file_sizes_on_db_open=false - skip_stats_update_on_db_open=false - recycle_log_file_num=0 - db_host_id=__hostname__ - access_hint_on_compaction_start=NORMAL - verify_sst_unique_id_in_manifest=true - track_and_verify_wals_in_manifest=false - error_if_exists=false - manifest_preallocation_size=4194304 - is_fd_close_on_exec=true - enable_write_thread_adaptive_yield=true - enable_thread_tracking=false - avoid_unnecessary_blocking_io=false - allow_fallocate=true - max_log_file_size=0 - advise_random_on_open=true - create_missing_column_families=true - max_write_batch_group_size_bytes=1048576 - use_adaptive_mutex=false - wal_filter=nullptr - create_if_missing=true - enforce_single_del_contracts=true - allow_mmap_writes=false - log_file_time_to_roll=0 - use_direct_io_for_flush_and_compaction=false - flush_verify_memtable_count=true - max_manifest_file_size=1073741824 - write_thread_max_yield_usec=100 - use_direct_reads=false - allow_mmap_reads=false - - -[CFOptions "default"] - memtable_protection_bytes_per_key=0 - bottommost_compression=kDisableCompressionOption - sample_for_compression=0 - blob_garbage_collection_age_cutoff=0.250000 - blob_compression_type=kNoCompression - prepopulate_blob_cache=kDisable - blob_compaction_readahead_size=0 - level0_stop_writes_trigger=36 - min_blob_size=0 - last_level_temperature=kUnknown - compaction_options_universal={allow_trivial_move=false;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;compression_size_percent=-1;max_size_amplification_percent=200;incremental=false;max_merge_width=4294967295;size_ratio=1;} - target_file_size_base=67108864 - ignore_max_compaction_bytes_for_input=true - memtable_whole_key_filtering=false - blob_file_starting_level=0 - soft_pending_compaction_bytes_limit=68719476736 - max_write_buffer_number=2 - ttl=2592000 - compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;} - check_flush_compaction_key_order=true - memtable_huge_page_size=0 - max_successive_merges=0 - inplace_update_num_locks=10000 - enable_blob_garbage_collection=false - arena_block_size=1048576 - bottommost_compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - target_file_size_multiplier=1 - max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1 - blob_garbage_collection_force_threshold=1.000000 - enable_blob_files=false - level0_slowdown_writes_trigger=20 - compression=kSnappyCompression - level0_file_num_compaction_trigger=4 - prefix_extractor=nullptr - max_bytes_for_level_multiplier=10.000000 - write_buffer_size=67108864 - disable_auto_compactions=false - max_compaction_bytes=1677721600 - compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - hard_pending_compaction_bytes_limit=274877906944 - blob_file_size=268435456 - periodic_compaction_seconds=0 - paranoid_file_checks=false - experimental_mempurge_threshold=0.000000 - memtable_prefix_bloom_size_ratio=0.000000 - max_bytes_for_level_base=268435456 - max_sequential_skip_in_iterations=8 - report_bg_io_stats=false - sst_partitioner_factory=nullptr - compaction_pri=kMinOverlappingRatio - compaction_style=kCompactionStyleLevel - compaction_filter_factory=nullptr - compaction_filter=nullptr - memtable_factory=SkipListFactory - comparator=leveldb.BytewiseComparator - bloom_locality=0 - min_write_buffer_number_to_merge=1 - table_factory=BlockBasedTable - max_write_buffer_size_to_maintain=0 - max_write_buffer_number_to_maintain=0 - preserve_internal_time_seconds=0 - force_consistency_checks=true - optimize_filters_for_hits=false - merge_operator=nullptr - num_levels=7 - level_compaction_dynamic_file_size=true - memtable_insert_with_hint_prefix_extractor=nullptr - level_compaction_dynamic_level_bytes=false - preclude_last_level_data_seconds=0 - inplace_update_support=false - -[TableOptions/BlockBasedTable "default"] - num_file_reads_for_auto_readahead=2 - metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;} - read_amp_bytes_per_bit=0 - verify_compression=false - format_version=5 - optimize_filters_for_memory=false - partition_filters=false - detect_filter_construct_corruption=false - initial_auto_readahead_size=8192 - max_auto_readahead_size=262144 - enable_index_compression=true - checksum=kXXH3 - index_block_restart_interval=1 - pin_top_level_index_and_filter=true - block_align=false - block_size=4096 - index_type=kBinarySearch - filter_policy=nullptr - metadata_block_size=4096 - no_block_cache=false - index_shortening=kShortenSeparators - whole_key_filtering=true - block_size_deviation=10 - data_block_index_type=kDataBlockBinarySearch - data_block_hash_table_util_ratio=0.750000 - cache_index_and_filter_blocks=false - prepopulate_block_cache=kDisable - block_restart_interval=16 - pin_l0_filter_and_index_blocks_in_cache=false - cache_index_and_filter_blocks_with_high_priority=true - flush_block_policy_factory=FlushBlockBySizePolicyFactory - - -[CFOptions "log"] - memtable_protection_bytes_per_key=0 - bottommost_compression=kZSTD - sample_for_compression=0 - blob_garbage_collection_age_cutoff=0.250000 - blob_compression_type=kNoCompression - prepopulate_blob_cache=kDisable - blob_compaction_readahead_size=0 - level0_stop_writes_trigger=36 - min_blob_size=0 - last_level_temperature=kUnknown - compaction_options_universal={allow_trivial_move=false;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;compression_size_percent=-1;max_size_amplification_percent=200;incremental=false;max_merge_width=4294967295;size_ratio=1;} - target_file_size_base=67108864 - ignore_max_compaction_bytes_for_input=true - memtable_whole_key_filtering=false - blob_file_starting_level=0 - soft_pending_compaction_bytes_limit=68719476736 - max_write_buffer_number=2 - ttl=2592000 - compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;} - check_flush_compaction_key_order=true - memtable_huge_page_size=0 - max_successive_merges=0 - inplace_update_num_locks=10000 - enable_blob_garbage_collection=false - arena_block_size=1048576 - bottommost_compression_opts={use_zstd_dict_trainer=true;enabled=true;parallel_threads=1;zstd_max_train_bytes=1048576;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - target_file_size_multiplier=1 - max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1 - blob_garbage_collection_force_threshold=1.000000 - enable_blob_files=false - level0_slowdown_writes_trigger=20 - compression=kLZ4Compression - level0_file_num_compaction_trigger=4 - prefix_extractor=nullptr - max_bytes_for_level_multiplier=10.000000 - write_buffer_size=67108864 - disable_auto_compactions=false - max_compaction_bytes=1677721600 - compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - hard_pending_compaction_bytes_limit=274877906944 - blob_file_size=268435456 - periodic_compaction_seconds=0 - paranoid_file_checks=false - experimental_mempurge_threshold=0.000000 - memtable_prefix_bloom_size_ratio=0.020000 - max_bytes_for_level_base=268435456 - max_sequential_skip_in_iterations=8 - report_bg_io_stats=false - sst_partitioner_factory=nullptr - compaction_pri=kMinOverlappingRatio - compaction_style=kCompactionStyleLevel - compaction_filter_factory=nullptr - compaction_filter=nullptr - memtable_factory=SkipListFactory - comparator=leveldb.BytewiseComparator - bloom_locality=0 - min_write_buffer_number_to_merge=1 - table_factory=BlockBasedTable - max_write_buffer_size_to_maintain=0 - max_write_buffer_number_to_maintain=0 - preserve_internal_time_seconds=0 - force_consistency_checks=true - optimize_filters_for_hits=false - merge_operator=nullptr - num_levels=7 - level_compaction_dynamic_file_size=true - memtable_insert_with_hint_prefix_extractor=nullptr - level_compaction_dynamic_level_bytes=false - preclude_last_level_data_seconds=0 - inplace_update_support=false - -[TableOptions/BlockBasedTable "log"] - num_file_reads_for_auto_readahead=2 - metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;} - read_amp_bytes_per_bit=0 - verify_compression=false - format_version=5 - optimize_filters_for_memory=false - partition_filters=false - detect_filter_construct_corruption=false - initial_auto_readahead_size=8192 - max_auto_readahead_size=262144 - enable_index_compression=true - checksum=kXXH3 - index_block_restart_interval=1 - pin_top_level_index_and_filter=true - block_align=false - block_size=16384 - index_type=kBinarySearch - filter_policy=bloomfilter - metadata_block_size=4096 - no_block_cache=false - index_shortening=kShortenSeparators - whole_key_filtering=true - block_size_deviation=10 - data_block_index_type=kDataBlockBinarySearch - data_block_hash_table_util_ratio=0.750000 - cache_index_and_filter_blocks=false - prepopulate_block_cache=kDisable - block_restart_interval=16 - pin_l0_filter_and_index_blocks_in_cache=true - cache_index_and_filter_blocks_with_high_priority=true - flush_block_policy_factory=FlushBlockBySizePolicyFactory - diff --git a/1/OPTIONS-000009 b/1/OPTIONS-000009 deleted file mode 100644 index 82283a0b5b7f1..0000000000000 --- a/1/OPTIONS-000009 +++ /dev/null @@ -1,304 +0,0 @@ -# This is a RocksDB option file. -# -# For detailed file format spec, please refer to the example file -# in examples/rocksdb_option_file_example.ini -# - -[Version] - rocksdb_version=8.1.1 - options_file_version=1.1 - -[DBOptions] - max_background_flushes=-1 - compaction_readahead_size=0 - strict_bytes_per_sync=false - wal_bytes_per_sync=0 - max_open_files=11520 - stats_history_buffer_size=1048576 - max_total_wal_size=1073741824 - stats_persist_period_sec=600 - stats_dump_period_sec=600 - avoid_flush_during_shutdown=false - max_subcompactions=1 - bytes_per_sync=0 - delayed_write_rate=16777216 - max_background_compactions=-1 - max_background_jobs=8 - delete_obsolete_files_period_micros=21600000000 - writable_file_max_buffer_size=1048576 - file_checksum_gen_factory=nullptr - allow_data_in_errors=false - max_bgerror_resume_count=2147483647 - best_efforts_recovery=false - write_dbid_to_manifest=false - atomic_flush=false - wal_compression=kNoCompression - manual_wal_flush=false - two_write_queues=false - avoid_flush_during_recovery=false - dump_malloc_stats=false - info_log_level=INFO_LEVEL - write_thread_slow_yield_usec=3 - allow_ingest_behind=false - fail_if_options_file_error=false - persist_stats_to_disk=false - WAL_ttl_seconds=0 - bgerror_resume_retry_interval=1000000 - allow_concurrent_memtable_write=true - paranoid_checks=true - WAL_size_limit_MB=0 - lowest_used_cache_tier=kNonVolatileBlockTier - keep_log_file_num=1000 - table_cache_numshardbits=10 - max_file_opening_threads=16 - use_fsync=false - unordered_write=false - random_access_max_buffer_size=1048576 - log_readahead_size=0 - enable_pipelined_write=true - wal_recovery_mode=kPointInTimeRecovery - db_write_buffer_size=1073741824 - allow_2pc=false - skip_checking_sst_file_sizes_on_db_open=false - skip_stats_update_on_db_open=false - recycle_log_file_num=0 - db_host_id=__hostname__ - access_hint_on_compaction_start=NORMAL - verify_sst_unique_id_in_manifest=true - track_and_verify_wals_in_manifest=false - error_if_exists=false - manifest_preallocation_size=4194304 - is_fd_close_on_exec=true - enable_write_thread_adaptive_yield=true - enable_thread_tracking=false - avoid_unnecessary_blocking_io=false - allow_fallocate=true - max_log_file_size=0 - advise_random_on_open=true - create_missing_column_families=true - max_write_batch_group_size_bytes=1048576 - use_adaptive_mutex=false - wal_filter=nullptr - create_if_missing=true - enforce_single_del_contracts=true - allow_mmap_writes=false - log_file_time_to_roll=0 - use_direct_io_for_flush_and_compaction=false - flush_verify_memtable_count=true - max_manifest_file_size=1073741824 - write_thread_max_yield_usec=100 - use_direct_reads=false - allow_mmap_reads=false - - -[CFOptions "default"] - memtable_protection_bytes_per_key=0 - bottommost_compression=kDisableCompressionOption - sample_for_compression=0 - blob_garbage_collection_age_cutoff=0.250000 - blob_compression_type=kNoCompression - prepopulate_blob_cache=kDisable - blob_compaction_readahead_size=0 - level0_stop_writes_trigger=36 - min_blob_size=0 - last_level_temperature=kUnknown - compaction_options_universal={allow_trivial_move=false;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;compression_size_percent=-1;max_size_amplification_percent=200;incremental=false;max_merge_width=4294967295;size_ratio=1;} - target_file_size_base=67108864 - ignore_max_compaction_bytes_for_input=true - memtable_whole_key_filtering=false - blob_file_starting_level=0 - soft_pending_compaction_bytes_limit=68719476736 - max_write_buffer_number=2 - ttl=2592000 - compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;} - check_flush_compaction_key_order=true - memtable_huge_page_size=0 - max_successive_merges=0 - inplace_update_num_locks=10000 - enable_blob_garbage_collection=false - arena_block_size=1048576 - bottommost_compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - target_file_size_multiplier=1 - max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1 - blob_garbage_collection_force_threshold=1.000000 - enable_blob_files=false - level0_slowdown_writes_trigger=20 - compression=kSnappyCompression - level0_file_num_compaction_trigger=4 - prefix_extractor=nullptr - max_bytes_for_level_multiplier=10.000000 - write_buffer_size=67108864 - disable_auto_compactions=false - max_compaction_bytes=1677721600 - compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - hard_pending_compaction_bytes_limit=274877906944 - blob_file_size=268435456 - periodic_compaction_seconds=0 - paranoid_file_checks=false - experimental_mempurge_threshold=0.000000 - memtable_prefix_bloom_size_ratio=0.000000 - max_bytes_for_level_base=268435456 - max_sequential_skip_in_iterations=8 - report_bg_io_stats=false - sst_partitioner_factory=nullptr - compaction_pri=kMinOverlappingRatio - compaction_style=kCompactionStyleLevel - compaction_filter_factory=nullptr - compaction_filter=nullptr - memtable_factory=SkipListFactory - comparator=leveldb.BytewiseComparator - bloom_locality=0 - min_write_buffer_number_to_merge=1 - table_factory=BlockBasedTable - max_write_buffer_size_to_maintain=0 - max_write_buffer_number_to_maintain=0 - preserve_internal_time_seconds=0 - force_consistency_checks=true - optimize_filters_for_hits=false - merge_operator=nullptr - num_levels=7 - level_compaction_dynamic_file_size=true - memtable_insert_with_hint_prefix_extractor=nullptr - level_compaction_dynamic_level_bytes=false - preclude_last_level_data_seconds=0 - inplace_update_support=false - -[TableOptions/BlockBasedTable "default"] - num_file_reads_for_auto_readahead=2 - metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;} - read_amp_bytes_per_bit=0 - verify_compression=false - format_version=5 - optimize_filters_for_memory=false - partition_filters=false - detect_filter_construct_corruption=false - initial_auto_readahead_size=8192 - max_auto_readahead_size=262144 - enable_index_compression=true - checksum=kXXH3 - index_block_restart_interval=1 - pin_top_level_index_and_filter=true - block_align=false - block_size=4096 - index_type=kBinarySearch - filter_policy=nullptr - metadata_block_size=4096 - no_block_cache=false - index_shortening=kShortenSeparators - whole_key_filtering=true - block_size_deviation=10 - data_block_index_type=kDataBlockBinarySearch - data_block_hash_table_util_ratio=0.750000 - cache_index_and_filter_blocks=false - prepopulate_block_cache=kDisable - block_restart_interval=16 - pin_l0_filter_and_index_blocks_in_cache=false - cache_index_and_filter_blocks_with_high_priority=true - flush_block_policy_factory=FlushBlockBySizePolicyFactory - - -[CFOptions "log"] - memtable_protection_bytes_per_key=0 - bottommost_compression=kZSTD - sample_for_compression=0 - blob_garbage_collection_age_cutoff=0.250000 - blob_compression_type=kNoCompression - prepopulate_blob_cache=kDisable - blob_compaction_readahead_size=0 - level0_stop_writes_trigger=36 - min_blob_size=0 - last_level_temperature=kUnknown - compaction_options_universal={allow_trivial_move=false;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;compression_size_percent=-1;max_size_amplification_percent=200;incremental=false;max_merge_width=4294967295;size_ratio=1;} - target_file_size_base=67108864 - ignore_max_compaction_bytes_for_input=true - memtable_whole_key_filtering=false - blob_file_starting_level=0 - soft_pending_compaction_bytes_limit=68719476736 - max_write_buffer_number=2 - ttl=2592000 - compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;} - check_flush_compaction_key_order=true - memtable_huge_page_size=0 - max_successive_merges=0 - inplace_update_num_locks=10000 - enable_blob_garbage_collection=false - arena_block_size=1048576 - bottommost_compression_opts={use_zstd_dict_trainer=true;enabled=true;parallel_threads=1;zstd_max_train_bytes=1048576;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - target_file_size_multiplier=1 - max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1 - blob_garbage_collection_force_threshold=1.000000 - enable_blob_files=false - level0_slowdown_writes_trigger=20 - compression=kLZ4Compression - level0_file_num_compaction_trigger=4 - prefix_extractor=nullptr - max_bytes_for_level_multiplier=10.000000 - write_buffer_size=67108864 - disable_auto_compactions=false - max_compaction_bytes=1677721600 - compression_opts={use_zstd_dict_trainer=true;enabled=false;parallel_threads=1;zstd_max_train_bytes=0;max_dict_bytes=0;strategy=0;max_dict_buffer_bytes=0;level=32767;window_bits=-14;} - hard_pending_compaction_bytes_limit=274877906944 - blob_file_size=268435456 - periodic_compaction_seconds=0 - paranoid_file_checks=false - experimental_mempurge_threshold=0.000000 - memtable_prefix_bloom_size_ratio=0.020000 - max_bytes_for_level_base=268435456 - max_sequential_skip_in_iterations=8 - report_bg_io_stats=false - sst_partitioner_factory=nullptr - compaction_pri=kMinOverlappingRatio - compaction_style=kCompactionStyleLevel - compaction_filter_factory=nullptr - compaction_filter=nullptr - memtable_factory=SkipListFactory - comparator=leveldb.BytewiseComparator - bloom_locality=0 - min_write_buffer_number_to_merge=1 - table_factory=BlockBasedTable - max_write_buffer_size_to_maintain=0 - max_write_buffer_number_to_maintain=0 - preserve_internal_time_seconds=0 - force_consistency_checks=true - optimize_filters_for_hits=false - merge_operator=nullptr - num_levels=7 - level_compaction_dynamic_file_size=true - memtable_insert_with_hint_prefix_extractor=nullptr - level_compaction_dynamic_level_bytes=false - preclude_last_level_data_seconds=0 - inplace_update_support=false - -[TableOptions/BlockBasedTable "log"] - num_file_reads_for_auto_readahead=2 - metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;} - read_amp_bytes_per_bit=0 - verify_compression=false - format_version=5 - optimize_filters_for_memory=false - partition_filters=false - detect_filter_construct_corruption=false - initial_auto_readahead_size=8192 - max_auto_readahead_size=262144 - enable_index_compression=true - checksum=kXXH3 - index_block_restart_interval=1 - pin_top_level_index_and_filter=true - block_align=false - block_size=16384 - index_type=kBinarySearch - filter_policy=bloomfilter - metadata_block_size=4096 - no_block_cache=false - index_shortening=kShortenSeparators - whole_key_filtering=true - block_size_deviation=10 - data_block_index_type=kDataBlockBinarySearch - data_block_hash_table_util_ratio=0.750000 - cache_index_and_filter_blocks=false - prepopulate_block_cache=kDisable - block_restart_interval=16 - pin_l0_filter_and_index_blocks_in_cache=true - cache_index_and_filter_blocks_with_high_priority=true - flush_block_policy_factory=FlushBlockBySizePolicyFactory - diff --git a/apps/core/README.md b/apps/core/README.md deleted file mode 100644 index d222a0bb15a95..0000000000000 --- a/apps/core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `@mysten/core` - -This JavaScript library contains helper utilities meant to be used across Mysten Lab's frontend applications. diff --git a/apps/core/package.json b/apps/core/package.json deleted file mode 100644 index ca18c44c9bd46..0000000000000 --- a/apps/core/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@mysten/core", - "main": "src/index.ts", - "private": true, - "sideEffects": false, - "author": "Mysten Labs ", - "repository": { - "type": "git", - "url": "github.com:MystenLabs/sui.git" - }, - "license": "Apache-2.0", - "scripts": { - "prettier:check": "prettier -c --ignore-unknown .", - "prettier:fix": "prettier -w --ignore-unknown .", - "prettier:fix:watch": "onchange '**' -i -f add -f change -j 5 -- prettier -w --ignore-unknown {{file}}", - "eslint:check": "eslint --max-warnings=0 .", - "eslint:fix": "pnpm run eslint:check --fix", - "lint": "pnpm run eslint:check && pnpm run prettier:check", - "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix", - "test": "vitest run", - "test:watch": "vitest" - }, - "dependencies": { - "@amplitude/analytics-client-common": "^0.7.0", - "@amplitude/analytics-core": "^0.13.3", - "@amplitude/analytics-types": "^0.20.0", - "@growthbook/growthbook-react": "^0.15.0", - "@hookform/resolvers": "^3.9.0", - "@mysten/dapp-kit": "^0.14.44", - "@mysten/kiosk": "^0.9.34", - "@mysten/sui": "^1.18.0", - "@sentry/react": "^7.59.2", - "@tanstack/react-query": "^5.50.1", - "bignumber.js": "^9.1.1", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-hook-form": "^7.52.1", - "vanilla-cookieconsent": "^2.9.1", - "zod": "^3.23.8" - }, - "devDependencies": { - "@headlessui/tailwindcss": "^0.1.3", - "@tailwindcss/aspect-ratio": "^0.4.2", - "@tailwindcss/forms": "^0.5.7", - "@types/react": "^18.3.3", - "@vanilla-extract/vite-plugin": "^4.0.13", - "postcss": "^8.4.39", - "tailwindcss": "^3.4.4", - "typescript": "^5.5.3", - "vite": "^5.3.3", - "vitest": "^2.0.1" - } -} diff --git a/apps/core/src/api/SentryHttpTransport.ts b/apps/core/src/api/SentryHttpTransport.ts deleted file mode 100644 index 0663523c77bf3..0000000000000 --- a/apps/core/src/api/SentryHttpTransport.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { SuiHTTPTransport } from '@mysten/sui/client'; -import * as Sentry from '@sentry/react'; - -const IGNORED_METHODS = ['suix_resolveNameServiceNames', 'suix_resolveNameServiceAddresses']; - -export class SentryHttpTransport extends SuiHTTPTransport { - #url: string; - constructor(url: string) { - super({ url }); - this.#url = url; - } - - async #withRequest(input: { method: string; params: unknown[] }, handler: () => Promise) { - const transaction = Sentry.startTransaction({ - name: input.method, - op: 'http.rpc-request', - data: input.params, - tags: { - url: this.#url, - }, - }); - - try { - const res = await handler(); - const status: Sentry.SpanStatusType = 'ok'; - transaction.setStatus(status); - return res; - } catch (e) { - const status: Sentry.SpanStatusType = 'internal_error'; - transaction.setStatus(status); - throw e; - } finally { - transaction.finish(); - } - } - - override async request(input: { method: string; params: unknown[] }) { - if (IGNORED_METHODS.includes(input.method)) { - return super.request(input); - } - - return this.#withRequest(input, () => super.request(input)); - } -} diff --git a/apps/core/src/components/KioskClientProvider.tsx b/apps/core/src/components/KioskClientProvider.tsx deleted file mode 100644 index 0475b9e79c36a..0000000000000 --- a/apps/core/src/components/KioskClientProvider.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClientContext } from '@mysten/dapp-kit'; -import { KioskClient, Network } from '@mysten/kiosk'; -import { createContext, useMemo, type ReactNode } from 'react'; - -export const KioskClientContext = createContext(null); - -const suiToKioskNetwork: Record = { - mainnet: Network.MAINNET, - testnet: Network.TESTNET, -}; - -export type KioskClientProviderProps = { - children: ReactNode; -}; - -export function KioskClientProvider({ children }: KioskClientProviderProps) { - const { client, network } = useSuiClientContext(); - const kioskNetwork = suiToKioskNetwork[network.toLowerCase()] || Network.CUSTOM; - const kioskClient = useMemo( - () => new KioskClient({ client, network: kioskNetwork }), - [client, kioskNetwork], - ); - return {children}; -} diff --git a/apps/core/src/css.d.ts b/apps/core/src/css.d.ts deleted file mode 100644 index 3c60c0cb9450b..0000000000000 --- a/apps/core/src/css.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -declare module '*.css' { - const css: string; - export default css; -} diff --git a/apps/core/src/hooks/__tests__/useFormatCoin.test.ts b/apps/core/src/hooks/__tests__/useFormatCoin.test.ts deleted file mode 100644 index d3f3c1f4edbfd..0000000000000 --- a/apps/core/src/hooks/__tests__/useFormatCoin.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import BigNumber from 'bignumber.js'; -import { describe, expect, it } from 'vitest'; - -import { CoinFormat, formatBalance } from '../useFormatCoin'; - -const SUI_DECIMALS = 9; - -function toMist(sui: string) { - return new BigNumber(sui).shiftedBy(SUI_DECIMALS).toString(); -} - -describe('formatBalance', () => { - it('formats zero amounts correctly', () => { - expect(formatBalance('0', 0)).toEqual('0'); - expect(formatBalance('0', SUI_DECIMALS)).toEqual('0'); - }); - - it('formats decimal amounts correctly', () => { - expect(formatBalance('0', SUI_DECIMALS)).toEqual('0'); - expect(formatBalance('0.000', SUI_DECIMALS)).toEqual('0'); - }); - - it('formats integer amounts correctly', () => { - expect(formatBalance(toMist('1'), SUI_DECIMALS)).toEqual('1'); - expect(formatBalance(toMist('1.0001'), SUI_DECIMALS)).toEqual('1'); - expect(formatBalance(toMist('1.1201'), SUI_DECIMALS)).toEqual('1.12'); - expect(formatBalance(toMist('1.1234'), SUI_DECIMALS)).toEqual('1.12'); - expect(formatBalance(toMist('1.1239'), SUI_DECIMALS)).toEqual('1.12'); - - expect(formatBalance(toMist('9999.9999'), SUI_DECIMALS)).toEqual('9,999.99'); - // 10k + handling: - expect(formatBalance(toMist('10000'), SUI_DECIMALS)).toEqual('10 K'); - expect(formatBalance(toMist('12345'), SUI_DECIMALS)).toEqual('12.34 K'); - // Millions: - expect(formatBalance(toMist('1234000'), SUI_DECIMALS)).toEqual('1.23 M'); - // Billions: - expect(formatBalance(toMist('1234000000'), SUI_DECIMALS)).toEqual('1.23 B'); - }); - - it('formats integer amounts with full CoinFormat', () => { - expect(formatBalance(toMist('1'), SUI_DECIMALS, CoinFormat.FULL)).toEqual('1'); - expect(formatBalance(toMist('1.123456789'), SUI_DECIMALS, CoinFormat.FULL)).toEqual( - '1.123456789', - ); - expect(formatBalance(toMist('9999.9999'), SUI_DECIMALS, CoinFormat.FULL)).toEqual('9,999.9999'); - expect(formatBalance(toMist('10000'), SUI_DECIMALS, CoinFormat.FULL)).toEqual('10,000'); - expect(formatBalance(toMist('12345'), SUI_DECIMALS, CoinFormat.FULL)).toEqual('12,345'); - expect(formatBalance(toMist('1234000'), SUI_DECIMALS, CoinFormat.FULL)).toEqual('1,234,000'); - expect(formatBalance(toMist('1234000000'), SUI_DECIMALS, CoinFormat.FULL)).toEqual( - '1,234,000,000', - ); - }); -}); diff --git a/apps/core/src/hooks/nameService.ts b/apps/core/src/hooks/nameService.ts deleted file mode 100644 index dc5587d749a1d..0000000000000 --- a/apps/core/src/hooks/nameService.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useFeatureIsOn } from '@growthbook/growthbook-react'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { useQuery } from '@tanstack/react-query'; - -const SUI_NS_FEATURE_FLAG = 'suins'; - -// This should align with whatever names we want to be able to resolve. - -export function useSuiNSEnabled() { - return useFeatureIsOn(SUI_NS_FEATURE_FLAG); -} - -export function useResolveSuiNSAddress(name?: string | null, enabled?: boolean) { - const client = useSuiClient(); - const enabledSuiNs = useSuiNSEnabled(); - - return useQuery({ - queryKey: ['resolve-suins-address', name], - queryFn: async () => { - return await client.resolveNameServiceAddress({ - name: name!, - }); - }, - enabled: !!name && enabled && enabledSuiNs, - refetchOnWindowFocus: false, - retry: false, - }); -} - -export function useResolveSuiNSName(address?: string | null) { - const client = useSuiClient(); - const enabled = useSuiNSEnabled(); - - return useQuery({ - queryKey: ['resolve-suins-name', address], - queryFn: async () => { - // NOTE: We only fetch 1 here because it's the default name. - const { data } = await client.resolveNameServiceNames({ - address: address!, - limit: 1, - }); - - return data[0] || null; - }, - enabled: !!address && enabled, - refetchOnWindowFocus: false, - retry: false, - }); -} diff --git a/apps/core/src/hooks/useAppsBackend.ts b/apps/core/src/hooks/useAppsBackend.ts deleted file mode 100644 index d5933a00b1127..0000000000000 --- a/apps/core/src/hooks/useAppsBackend.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useCallback } from 'react'; - -const backendUrl = - process.env.NODE_ENV === 'development' ? 'http://localhost:3003' : 'https://apps-backend.sui.io'; - -export function useAppsBackend() { - const request = useCallback( - async ( - path: string, - queryParams?: Record, - options?: RequestInit, - ): Promise => { - const res = await fetch(formatRequestURL(`${backendUrl}/${path}`, queryParams), options); - - if (!res.ok) { - throw new Error('Unexpected response'); - } - - return res.json(); - }, - [], - ); - - return { request }; -} - -function formatRequestURL(url: string, queryParams?: Record) { - if (queryParams && Object.keys(queryParams).length > 0) { - const searchParams = new URLSearchParams(queryParams); - return `${url}?${searchParams}`; - } - return url; -} diff --git a/apps/core/src/hooks/useCookieConsentBanner.ts b/apps/core/src/hooks/useCookieConsentBanner.ts deleted file mode 100644 index 230abfcbb9476..0000000000000 --- a/apps/core/src/hooks/useCookieConsentBanner.ts +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; - -import { PersistableStorage } from '../utils/persistableStorage'; -import { useProductAnalyticsConfig } from './useProductAnalyticsConfig'; - -export const ANALYTICS_COOKIE_CATEGORY = 'analytics'; -export const NECESSARY_COOKIE_CATEGORY = 'necessary'; - -type CookieConsentConfig = UserConfig & { onBeforeLoad: () => void }; - -export function useCookieConsentBanner( - storageInstance: PersistableStorage, - options: CookieConsentConfig, -) { - const { data: productAnalyticsConfig } = useProductAnalyticsConfig(); - - useEffect(() => { - if (productAnalyticsConfig) { - if (productAnalyticsConfig.mustProvideCookieConsent) { - loadCookieConsentBanner(storageInstance, options); - } else { - // Use cookie storage if the user doesn't have to provide consent - storageInstance.persist(); - } - } - }, [options, productAnalyticsConfig, storageInstance]); -} - -async function loadCookieConsentBanner( - storageInstance: PersistableStorage, - options: CookieConsentConfig, -) { - await import('vanilla-cookieconsent'); - await import('vanilla-cookieconsent/dist/cookieconsent.css'); - await options.onBeforeLoad(); - - const cookieConsent = window.initCookieConsent(); - cookieConsent.run({ - revision: 0, - autorun: true, - current_lang: 'en', - gui_options: { - consent_modal: { - layout: 'box', - position: 'bottom right', - transition: 'slide', - swap_buttons: true, - }, - settings_modal: { - layout: 'box', - transition: 'slide', - }, - }, - languages: { - en: { - consent_modal: { - title: 'We use cookies!', - description: - 'Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only upon approval.', - primary_btn: { - text: 'Accept All', - role: 'accept_all', - }, - secondary_btn: { - text: 'Reject All', - role: 'accept_necessary', - }, - }, - settings_modal: { - title: 'Cookie preferences', - save_settings_btn: 'Save settings', - accept_all_btn: 'Accept all', - reject_all_btn: 'Reject all', - blocks: [ - { - title: 'Cookie usage', - description: - 'We use cookies to ensure the basic functionalities of the website and to enhance your online experience. For more details relative to cookies and other sensitive data, please read the full privacy policy.', - }, - { - title: 'Strictly necessary cookies', - description: - 'These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly.', - toggle: { - value: NECESSARY_COOKIE_CATEGORY, - enabled: true, - readonly: true, - }, - }, - { - title: 'Analytics cookies', - description: - 'These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you.', - toggle: { - value: ANALYTICS_COOKIE_CATEGORY, - enabled: false, - readonly: false, - }, - }, - ], - }, - }, - }, - onChange: (cookieContent) => { - if (cookieContent.categories.includes(ANALYTICS_COOKIE_CATEGORY)) { - storageInstance.persist(); - } else { - storageInstance.reset(); - } - }, - onAccept: (cookieContent) => { - if (cookieContent.categories.includes(ANALYTICS_COOKIE_CATEGORY)) { - storageInstance.persist(); - } - }, - ...options, - }); -} diff --git a/apps/core/src/hooks/useCopyToClipboard.ts b/apps/core/src/hooks/useCopyToClipboard.ts deleted file mode 100644 index 9ca94db861456..0000000000000 --- a/apps/core/src/hooks/useCopyToClipboard.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useCallback } from 'react'; - -export function useCopyToClipboard(onSuccessCallback?: () => void) { - return useCallback( - async (text: string) => { - if (!navigator?.clipboard) { - return false; - } - - try { - await navigator.clipboard.writeText(text); - if (onSuccessCallback) { - onSuccessCallback(); - } - return true; - } catch (error) { - return false; - } - }, - [onSuccessCallback], - ); -} diff --git a/apps/core/src/hooks/useElementDimensions.ts b/apps/core/src/hooks/useElementDimensions.ts deleted file mode 100644 index f2b0f30e55075..0000000000000 --- a/apps/core/src/hooks/useElementDimensions.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { RefObject, useEffect, useState } from 'react'; - -export function useElementDimensions( - elementRef: RefObject, - defaultHeight: number = 0, - defaultWidth: number = 0, -) { - const [height, setHeight] = useState(defaultHeight); - const [width, setWidth] = useState(defaultWidth); - - useEffect(() => { - const resizeObserver = new ResizeObserver((entries) => { - for (const entry of entries) { - const entryHeight = entry.contentRect.height; - const entryWidth = entry.contentRect.width; - - if (entryHeight !== height) { - setHeight(entryHeight); - } - - if (entryWidth !== width) { - setWidth(entryWidth); - } - } - }); - - if (elementRef.current) { - resizeObserver.observe(elementRef.current); - } - - const headerCurrentRef = elementRef.current; - - return () => { - if (headerCurrentRef) { - resizeObserver.unobserve(headerCurrentRef); - } - }; - }, [elementRef, height, width]); - - return [height, width]; -} diff --git a/apps/core/src/hooks/useFormatCoin.ts b/apps/core/src/hooks/useFormatCoin.ts deleted file mode 100644 index a4ed34fcc987f..0000000000000 --- a/apps/core/src/hooks/useFormatCoin.ts +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { CoinMetadata } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useQuery, type UseQueryResult } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; -import { useMemo } from 'react'; - -import { formatAmount } from '../utils/formatAmount'; - -type FormattedCoin = [ - formattedBalance: string, - coinSymbol: string, - queryResult: UseQueryResult, -]; - -export enum CoinFormat { - ROUNDED = 'ROUNDED', - FULL = 'FULL', -} - -/** - * Formats a coin balance based on our standard coin display logic. - * If the balance is less than 1, it will be displayed in its full decimal form. - * For values greater than 1, it will be truncated to 3 decimal places. - */ -export function formatBalance( - balance: bigint | number | string, - decimals: number, - format: CoinFormat = CoinFormat.ROUNDED, -) { - const bn = new BigNumber(balance.toString()).shiftedBy(-1 * decimals); - - if (format === CoinFormat.FULL) { - return bn.toFormat(); - } - - return formatAmount(bn); -} - -const ELLIPSIS = '\u{2026}'; -const SYMBOL_TRUNCATE_LENGTH = 5; -const NAME_TRUNCATE_LENGTH = 10; - -type CoinMetadataOverrides = { - [coinType: string]: { - name?: string; - iconUrl?: string; - symbol?: string; - }; -}; - -export function useCoinMetadata(coinType?: string | null) { - const client = useSuiClient(); - const tokenMetadataOverrides = useFeatureValue( - 'token-metadata-overrides', - {}, - ); - - return useQuery({ - queryKey: ['coin-metadata', coinType], - queryFn: async () => { - if (!coinType) { - throw new Error('Fetching coin metadata should be disabled when coin type is disabled.'); - } - - // Optimize the known case of SUI to avoid a network call: - if (coinType === SUI_TYPE_ARG) { - const metadata: CoinMetadata = { - id: null, - decimals: 9, - description: '', - iconUrl: null, - name: 'Sui', - symbol: 'SUI', - }; - - return metadata; - } - - return client.getCoinMetadata({ coinType }); - }, - select(data) { - if (!data) return null; - - const symbol = - coinType && tokenMetadataOverrides[coinType]?.symbol - ? tokenMetadataOverrides[coinType].symbol - : data.symbol; - const name = - coinType && tokenMetadataOverrides[coinType]?.name - ? tokenMetadataOverrides[coinType].name - : data.name; - - return { - ...data, - iconUrl: - coinType && tokenMetadataOverrides[coinType]?.iconUrl - ? tokenMetadataOverrides[coinType].iconUrl - : data.iconUrl, - symbol: - symbol.length > SYMBOL_TRUNCATE_LENGTH - ? symbol.slice(0, SYMBOL_TRUNCATE_LENGTH) + ELLIPSIS - : symbol, - name: - name.length > NAME_TRUNCATE_LENGTH - ? name.slice(0, NAME_TRUNCATE_LENGTH) + ELLIPSIS - : name, - }; - }, - retry: false, - enabled: !!coinType, - staleTime: Infinity, - gcTime: 24 * 60 * 60 * 1000, - }); -} - -// TODO #1: This handles undefined values to make it easier to integrate with -// the reset of the app as it is today, but it really shouldn't in a perfect world. -export function useFormatCoin( - balance?: bigint | number | string | null, - coinType?: string | null, - format: CoinFormat = CoinFormat.ROUNDED, -): FormattedCoin { - const fallbackSymbol = useMemo(() => (coinType ? getCoinSymbol(coinType) ?? '' : ''), [coinType]); - - const queryResult = useCoinMetadata(coinType); - const { isFetched, data } = queryResult; - - const formatted = useMemo(() => { - if (typeof balance === 'undefined' || balance === null) return ''; - - if (!isFetched) return '...'; - - return formatBalance(balance, data?.decimals ?? 0, format); - }, [data?.decimals, isFetched, balance, format]); - - return [formatted, isFetched ? data?.symbol || fallbackSymbol : '', queryResult]; -} - -/** @deprecated use coin metadata instead */ -export function getCoinSymbol(coinTypeArg: string) { - return coinTypeArg.substring(coinTypeArg.lastIndexOf(':') + 1); -} diff --git a/apps/core/src/hooks/useGetCoins.ts b/apps/core/src/hooks/useGetCoins.ts deleted file mode 100644 index 42ae6125c7dfb..0000000000000 --- a/apps/core/src/hooks/useGetCoins.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import { PaginatedCoins } from '@mysten/sui/client'; -import { useInfiniteQuery } from '@tanstack/react-query'; - -const MAX_COINS_PER_REQUEST = 10; - -export function useGetCoins( - coinType: string, - address?: string | null, - maxCoinsPerRequest = MAX_COINS_PER_REQUEST, -) { - const client = useSuiClient(); - return useInfiniteQuery({ - queryKey: ['get-coins', address, coinType, maxCoinsPerRequest], - initialPageParam: null, - getNextPageParam: ({ hasNextPage, nextCursor }) => (hasNextPage ? nextCursor : null), - queryFn: ({ pageParam }) => - client.getCoins({ - owner: address!, - coinType, - cursor: pageParam as string | null, - limit: maxCoinsPerRequest, - }), - enabled: !!address, - }); -} diff --git a/apps/core/src/hooks/useGetDelegatedStake.tsx b/apps/core/src/hooks/useGetDelegatedStake.tsx deleted file mode 100644 index eca438fd4d808..0000000000000 --- a/apps/core/src/hooks/useGetDelegatedStake.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import type { DelegatedStake } from '@mysten/sui/client'; -import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; - -type UseGetDelegatedStakesOptions = { - address: string; -} & Omit, 'queryKey' | 'queryFn'>; - -export function useGetDelegatedStake(options: UseGetDelegatedStakesOptions) { - const client = useSuiClient(); - const { address, ...queryOptions } = options; - - return useQuery({ - queryKey: ['delegated-stakes', address], - queryFn: () => client.getStakes({ owner: address }), - ...queryOptions, - }); -} diff --git a/apps/core/src/hooks/useGetDynamicFields.ts b/apps/core/src/hooks/useGetDynamicFields.ts deleted file mode 100644 index 144d831995fe4..0000000000000 --- a/apps/core/src/hooks/useGetDynamicFields.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import { DynamicFieldPage } from '@mysten/sui/client'; -import { normalizeSuiAddress } from '@mysten/sui/utils'; -import { useInfiniteQuery } from '@tanstack/react-query'; - -const MAX_PAGE_SIZE = 10; - -export function useGetDynamicFields(parentId: string, maxPageSize = MAX_PAGE_SIZE) { - const client = useSuiClient(); - return useInfiniteQuery({ - queryKey: ['dynamic-fields', { maxPageSize, parentId }], - queryFn: ({ pageParam = null }) => - client.getDynamicFields({ - parentId: normalizeSuiAddress(parentId), - cursor: pageParam as string | null, - limit: maxPageSize, - }), - enabled: !!parentId, - initialPageParam: null, - getNextPageParam: ({ nextCursor, hasNextPage }) => (hasNextPage ? nextCursor : null), - }); -} diff --git a/apps/core/src/hooks/useGetKioskContents.ts b/apps/core/src/hooks/useGetKioskContents.ts deleted file mode 100644 index c5d6e42c741e3..0000000000000 --- a/apps/core/src/hooks/useGetKioskContents.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClientContext } from '@mysten/dapp-kit'; -import { KIOSK_ITEM, KioskClient, KioskItem, KioskOwnerCap } from '@mysten/kiosk'; -import { SuiClient } from '@mysten/sui/client'; -import { useQuery } from '@tanstack/react-query'; - -import { getKioskIdFromOwnerCap, ORIGINBYTE_KIOSK_OWNER_TOKEN } from '../utils/kiosk'; -import { useKioskClient } from './useKioskClient'; - -export enum KioskTypes { - SUI = 'sui', - ORIGINBYTE = 'originByte', -} - -export type Kiosk = { - items: KioskItem[]; - itemIds: string[]; - kioskId: string; - type: KioskTypes; - ownerCap?: KioskOwnerCap; -}; - -async function getOriginByteKioskContents(address: string, client: SuiClient) { - const data = await client.getOwnedObjects({ - owner: address, - filter: { - StructType: ORIGINBYTE_KIOSK_OWNER_TOKEN, - }, - options: { - showContent: true, - }, - }); - const ids = data.data.map((object) => getKioskIdFromOwnerCap(object)); - - // fetch the user's kiosks - const ownedKiosks = await client.multiGetObjects({ - ids: ids.flat(), - options: { - showContent: true, - }, - }); - - const contents = await Promise.all( - ownedKiosks - .map(async (kiosk) => { - if (!kiosk.data) return; - const objects = await client.getDynamicFields({ - parentId: kiosk.data.objectId, - }); - - const objectIds = objects.data - .filter((obj) => obj.name.type === KIOSK_ITEM) - .map((obj) => obj.objectId); - - // fetch the contents of the objects within a kiosk - const kioskContent = await client.multiGetObjects({ - ids: objectIds, - options: { - showDisplay: true, - showType: true, - }, - }); - - return { - itemIds: objectIds, - items: kioskContent.map((item) => ({ ...item, kioskId: kiosk.data?.objectId })), - kioskId: kiosk.data.objectId, - type: KioskTypes.ORIGINBYTE, - }; - }) - .filter(Boolean) as Promise[], - ); - return contents; -} - -async function getSuiKioskContents(address: string, kioskClient: KioskClient) { - const ownedKiosks = await kioskClient.getOwnedKiosks({ address }); - const contents = await Promise.all( - ownedKiosks.kioskIds.map(async (id: string) => { - const kiosk = await kioskClient.getKiosk({ - id, - options: { - withObjects: true, - objectOptions: { showDisplay: true, showContent: true }, - }, - }); - return { - itemIds: kiosk.itemIds, - items: kiosk.items, - kioskId: id, - type: KioskTypes.SUI, - ownerCap: ownedKiosks.kioskOwnerCaps.find((k) => k.kioskId === id), - }; - }), - ); - return contents; -} - -export function useGetKioskContents(address?: string | null, disableOriginByteKiosk?: boolean) { - const { client: suiClient, network } = useSuiClientContext(); - const kioskClient = useKioskClient(); - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ['get-kiosk-contents', address, disableOriginByteKiosk, network, kioskClient.network], - queryFn: async () => { - const suiKiosks = await getSuiKioskContents(address!, kioskClient); - const obKiosks = await getOriginByteKioskContents(address!, suiClient); - return [...suiKiosks, ...obKiosks]; - }, - select(data) { - const kiosks = new Map(); - const lookup = new Map(); - - data.forEach((kiosk) => { - kiosks.set(kiosk.kioskId, kiosk); - kiosk.itemIds.forEach((id) => { - lookup.set(id, kiosk.kioskId); - }); - }); - - return { - kiosks, - list: data.flatMap((kiosk) => kiosk.items), - lookup, - }; - }, - enabled: !!address, - }); -} diff --git a/apps/core/src/hooks/useGetObject.ts b/apps/core/src/hooks/useGetObject.ts deleted file mode 100644 index dcafed16752f5..0000000000000 --- a/apps/core/src/hooks/useGetObject.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import { normalizeSuiAddress } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; - -const defaultOptions = { - showType: true, - showContent: true, - showOwner: true, - showPreviousTransaction: true, - showStorageRebate: true, - showDisplay: true, -}; - -export function useGetObject(objectId?: string | null) { - const client = useSuiClient(); - const normalizedObjId = objectId && normalizeSuiAddress(objectId); - return useQuery({ - queryKey: ['object', normalizedObjId], - queryFn: () => - client.getObject({ - id: normalizedObjId!, - options: defaultOptions, - }), - enabled: !!normalizedObjId, - }); -} diff --git a/apps/core/src/hooks/useGetOwnedObjects.ts b/apps/core/src/hooks/useGetOwnedObjects.ts deleted file mode 100644 index d43629f19d328..0000000000000 --- a/apps/core/src/hooks/useGetOwnedObjects.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import { PaginatedObjectsResponse, type SuiObjectDataFilter } from '@mysten/sui/client'; -import { useInfiniteQuery } from '@tanstack/react-query'; - -const MAX_OBJECTS_PER_REQ = 6; - -export function useGetOwnedObjects( - address?: string | null, - filter?: SuiObjectDataFilter, - maxObjectRequests = MAX_OBJECTS_PER_REQ, -) { - const client = useSuiClient(); - return useInfiniteQuery({ - initialPageParam: null, - queryKey: ['get-owned-objects', address, filter, maxObjectRequests], - queryFn: ({ pageParam }) => - client.getOwnedObjects({ - owner: address!, - filter, - options: { - showType: true, - showContent: true, - showDisplay: true, - }, - limit: maxObjectRequests, - cursor: pageParam as string | null, - }), - - staleTime: 10 * 1000, - enabled: !!address, - getNextPageParam: ({ hasNextPage, nextCursor }) => (hasNextPage ? nextCursor : null), - }); -} diff --git a/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts b/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts deleted file mode 100644 index b9738d3477080..0000000000000 --- a/apps/core/src/hooks/useGetTimeBeforeEpochNumber.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClientQuery } from '@mysten/dapp-kit'; - -// Get time between current epoch and specified epoch -// Get the period between the current epoch and next epoch -export function useGetTimeBeforeEpochNumber(epoch: number) { - const data = useSuiClientQuery('getLatestSuiSystemState'); - // Current epoch - const currentEpoch = Number(data.data?.epoch || 0); - const currentEpochStartTime = Number(data.data?.epochStartTimestampMs || 0); - const epochPeriod = Number(data.data?.epochDurationMs || 0); - const timeBeforeSpecifiedEpoch = - epoch > currentEpoch && epoch > 0 && epochPeriod > 0 - ? currentEpochStartTime + (epoch - currentEpoch) * epochPeriod - : 0; - - return { - ...data, - data: timeBeforeSpecifiedEpoch, - }; -} diff --git a/apps/core/src/hooks/useGetTransferAmount.ts b/apps/core/src/hooks/useGetTransferAmount.ts deleted file mode 100644 index 52b5fe859fc4b..0000000000000 --- a/apps/core/src/hooks/useGetTransferAmount.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -import { getTotalGasUsed } from '../utils/transaction'; - -export function useGetTransferAmount(txnData: SuiTransactionBlockResponse) { - const { balanceChanges } = txnData; - const sender = txnData.transaction?.data.sender; - const gas = txnData.effects && getTotalGasUsed(txnData.effects); - const changes = useMemo( - () => - balanceChanges - ? balanceChanges?.map(({ coinType, owner, amount }) => ({ - coinType, - address: - owner === 'Immutable' - ? 'Immutable' - : 'AddressOwner' in owner - ? owner.AddressOwner - : 'ObjectOwner' in owner - ? owner.ObjectOwner - : '', - amount: - coinType === SUI_TYPE_ARG && BigInt(amount) < 0n - ? BigInt(amount) + BigInt(gas ?? 0n) - : BigInt(amount), - })) - : [], - [balanceChanges, gas], - ); - // take absolute value of the first balance change entry for display - const [change] = changes; - const amount = change?.amount ? (change.amount < 0n ? -change.amount : change.amount) : 0n; - - return { - balanceChanges: changes, - coinType: change?.coinType, - gas, - sender, - amount, - }; -} diff --git a/apps/core/src/hooks/useGetValidatorsApy.ts b/apps/core/src/hooks/useGetValidatorsApy.ts deleted file mode 100644 index b5e00df35aa88..0000000000000 --- a/apps/core/src/hooks/useGetValidatorsApy.ts +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient, useSuiClientQuery } from '@mysten/dapp-kit'; -import { useQuery } from '@tanstack/react-query'; - -import { roundFloat } from '../utils/roundFloat'; - -// recentEpochRewards is list of the last 30 epoch rewards for a specific validator -// APY_e = (1 + epoch_rewards / stake)^365-1 -// APY_e_30rollingaverage = average(APY_e,APY_e-1,…,APY_e-29); - -const DEFAULT_APY_DECIMALS = 2; - -export interface ApyByValidator { - [validatorAddress: string]: { - apy: number; - isApyApproxZero: boolean; - }; -} -// For small APY or epoch before stakeSubsidyStartEpoch, show ~0% instead of 0% -// If APY falls below 0.001, show ~0% instead of 0% since we round to 2 decimal places -const MINIMUM_THRESHOLD = 0.001; - -export function useGetValidatorsApy() { - const client = useSuiClient(); - const { data: systemStateResponse, isFetched } = useSuiClientQuery('getLatestSuiSystemState'); - return useQuery({ - queryKey: ['get-rolling-average-apys'], - queryFn: () => client.getValidatorsApy(), - enabled: isFetched, - select: (validatorApys) => { - // check if stakeSubsidyStartEpoch is greater than current epoch, flag for UI to show ~0% instead of 0% - const currentEpoch = Number(systemStateResponse?.epoch); - const stakeSubsidyStartEpoch = Number(systemStateResponse?.stakeSubsidyStartEpoch); - - const isStakeSubsidyStarted = currentEpoch > stakeSubsidyStartEpoch; - - return validatorApys?.apys.reduce((acc, { apy, address }) => { - acc[address] = { - apy: roundFloat(apy * 100, DEFAULT_APY_DECIMALS), - isApyApproxZero: !isStakeSubsidyStarted || apy < MINIMUM_THRESHOLD, - }; - return acc; - }, {} as ApyByValidator); - }, - }); -} diff --git a/apps/core/src/hooks/useGetValidatorsEvents.ts b/apps/core/src/hooks/useGetValidatorsEvents.ts deleted file mode 100644 index 3948757fe649e..0000000000000 --- a/apps/core/src/hooks/useGetValidatorsEvents.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useSuiClient } from '@mysten/dapp-kit'; -import { SuiEvent, type EventId } from '@mysten/sui/client'; -import { useQuery } from '@tanstack/react-query'; - -type GetValidatorsEvent = { - limit: number | null; - order: 'ascending' | 'descending'; -}; - -// NOTE: This copys the query limit from our Rust JSON RPC backend, this needs to be kept in sync! -const QUERY_MAX_RESULT_LIMIT = 50; -const VALIDATORS_EVENTS_QUERY = '0x3::validator_set::ValidatorEpochInfoEventV2'; - -//TODO: get validatorEvents by validator address -export function useGetValidatorsEvents({ limit, order }: GetValidatorsEvent) { - const client = useSuiClient(); - // Since we are getting events based on the number of validators, we need to make sure that the limit - // is not null and cache by the limit number of validators can change from network to network - return useQuery({ - queryKey: ['validatorEvents', limit, order], - queryFn: async () => { - if (!limit) { - // Do some validation at the runtime level for some extra type-safety - // https://tkdodo.eu/blog/react-query-and-type-script#type-safety-with-the-enabled-option - throw new Error( - `Limit needs to always be defined and non-zero! Received ${limit} instead.`, - ); - } - - if (limit > QUERY_MAX_RESULT_LIMIT) { - let hasNextPage = true; - let currCursor: EventId | null | undefined; - const results: SuiEvent[] = []; - - while (hasNextPage && results.length < limit) { - const validatorEventsResponse = await client.queryEvents({ - query: { MoveEventType: VALIDATORS_EVENTS_QUERY }, - cursor: currCursor, - limit: Math.min(limit, QUERY_MAX_RESULT_LIMIT), - order, - }); - - hasNextPage = validatorEventsResponse.hasNextPage; - currCursor = validatorEventsResponse.nextCursor; - results.push(...(validatorEventsResponse.data as SuiEvent[])); - } - return results.slice(0, limit); - } - - const validatorEventsResponse = await client.queryEvents({ - query: { MoveEventType: VALIDATORS_EVENTS_QUERY }, - limit, - order, - }); - return validatorEventsResponse.data; - }, - enabled: !!limit, - }); -} diff --git a/apps/core/src/hooks/useKioskClient.ts b/apps/core/src/hooks/useKioskClient.ts deleted file mode 100644 index 5b2392519d2cb..0000000000000 --- a/apps/core/src/hooks/useKioskClient.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useContext } from 'react'; - -import { KioskClientContext } from '../components/KioskClientProvider'; - -export function useKioskClient() { - const kioskClient = useContext(KioskClientContext); - if (!kioskClient) { - throw new Error('Kiosk client not found. Please make sure KioskClientProvider is set up.'); - } - return kioskClient; -} diff --git a/apps/core/src/hooks/useLocalStorage.ts b/apps/core/src/hooks/useLocalStorage.ts deleted file mode 100644 index 201ab23355c5d..0000000000000 --- a/apps/core/src/hooks/useLocalStorage.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Dispatch, SetStateAction, useCallback, useState } from 'react'; - -type SetValue = Dispatch>; - -export function useLocalStorage(key: string, initialValue: T): [T, SetValue] { - const getValue = useCallback(() => { - try { - const item = window.localStorage.getItem(key); - return item ? (JSON.parse(item) as T) : initialValue; - } catch (error) { - console.warn(`Error reading localStorage key "${key}":`, error); - return initialValue; - } - }, [initialValue, key]); - - const [storedValue, setStoredValue] = useState(getValue); - - const setValue: SetValue = useCallback( - (value) => { - if (typeof window === 'undefined') { - console.warn(`Tried setting localStorage key "${key}" even though window is not defined`); - } - - try { - const newValue = value instanceof Function ? value(storedValue) : value; - window.localStorage.setItem(key, JSON.stringify(newValue)); - setStoredValue(newValue); - } catch (error) { - console.warn(`Error setting localStorage key "${key}":`, error); - } - }, - [key, storedValue], - ); - - return [storedValue, setValue]; -} diff --git a/apps/core/src/hooks/useMultiGetObjects.ts b/apps/core/src/hooks/useMultiGetObjects.ts deleted file mode 100644 index f01804576b26c..0000000000000 --- a/apps/core/src/hooks/useMultiGetObjects.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import { SuiObjectDataOptions, SuiObjectResponse } from '@mysten/sui/client'; -import { useQuery, UseQueryOptions } from '@tanstack/react-query'; - -import { chunkArray } from '../utils/chunkArray'; - -export function useMultiGetObjects( - ids: string[], - options: SuiObjectDataOptions, - queryOptions?: Omit, 'queryKey' | 'queryFn'>, -) { - const client = useSuiClient(); - return useQuery({ - ...queryOptions, - queryKey: ['multiGetObjects', ids], - queryFn: async () => { - const responses = await Promise.all( - chunkArray(ids, 50).map((chunk) => - client.multiGetObjects({ - ids: chunk, - options, - }), - ), - ); - return responses.flat(); - }, - enabled: !!ids?.length, - }); -} diff --git a/apps/core/src/hooks/useOnScreen.ts b/apps/core/src/hooks/useOnScreen.ts deleted file mode 100644 index 0cfad1ef4ece7..0000000000000 --- a/apps/core/src/hooks/useOnScreen.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { MutableRefObject, useEffect, useState } from 'react'; - -export const useOnScreen = (elementRef: MutableRefObject) => { - const [isIntersecting, setIsIntersecting] = useState(false); - - useEffect(() => { - const node = elementRef.current; - if (!node) return; - - const observer = new IntersectionObserver( - ([entry]: IntersectionObserverEntry[]): void => { - setIsIntersecting(entry.isIntersecting); - }, - { threshold: 0.01 }, - ); - observer.observe(node); - return () => observer.disconnect(); - }, [elementRef]); - - return { isIntersecting }; -}; diff --git a/apps/core/src/hooks/useProductAnalyticsConfig.ts b/apps/core/src/hooks/useProductAnalyticsConfig.ts deleted file mode 100644 index faa856854e030..0000000000000 --- a/apps/core/src/hooks/useProductAnalyticsConfig.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; - -import { useAppsBackend } from './useAppsBackend'; - -type ProductAnalyticsConfigResponse = { mustProvideCookieConsent: boolean }; - -export function useProductAnalyticsConfig() { - const { request } = useAppsBackend(); - return useQuery({ - queryKey: ['apps-backend', 'product-analytics-config'], - queryFn: () => request('product-analytics'), - staleTime: 24 * 60 * 60 * 1000, - gcTime: Infinity, - }); -} diff --git a/apps/core/src/hooks/useSuiCoinData.ts b/apps/core/src/hooks/useSuiCoinData.ts deleted file mode 100644 index d09b4fd519519..0000000000000 --- a/apps/core/src/hooks/useSuiCoinData.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; - -import { useAppsBackend } from './useAppsBackend'; - -// TODO: We should consider using tRPC or something for apps-backend -type CoinData = { - marketCap: string; - fullyDilutedMarketCap: string; - currentPrice: number; - priceChangePercentageOver24H: number; - circulatingSupply: number; - totalSupply: number; -}; - -export const COIN_GECKO_SUI_URL = 'https://www.coingecko.com/en/coins/sui'; - -export function useSuiCoinData() { - const { request } = useAppsBackend(); - return useQuery({ - queryKey: ['sui-coin-data'], - queryFn: () => request('coins/sui', {}), - gcTime: 24 * 60 * 60 * 1000, - staleTime: Infinity, - }); -} diff --git a/apps/core/src/hooks/useTimeAgo.ts b/apps/core/src/hooks/useTimeAgo.ts deleted file mode 100644 index 18fece3d7e250..0000000000000 --- a/apps/core/src/hooks/useTimeAgo.ts +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect, useMemo, useState } from 'react'; - -const TIME_LABEL = { - year: { - full: 'year', - short: 'y', - }, - month: { - full: 'month', - short: 'm', - }, - day: { - full: 'day', - short: 'd', - }, - hour: { - full: 'hour', - short: 'h', - }, - min: { - full: 'min', - short: 'm', - }, - sec: { - full: 'sec', - short: 's', - }, -}; - -export enum TimeUnit { - ONE_SECOND = 1000, - ONE_MINUTE = TimeUnit.ONE_SECOND * 60, - ONE_HOUR = TimeUnit.ONE_MINUTE * 60, - ONE_DAY = TimeUnit.ONE_HOUR * 24, -} - -/** - * Formats a timestamp using `timeAgo`, and automatically updates it when the value is small. - */ - -type TimeAgoOptions = { - timeFrom: number | null; - shortedTimeLabel: boolean; - shouldEnd?: boolean; - endLabel?: string; - maxTimeUnit?: TimeUnit; -}; - -export function useTimeAgo(options: TimeAgoOptions) { - const { timeFrom, shortedTimeLabel, shouldEnd, endLabel, maxTimeUnit } = options; - const [now, setNow] = useState(() => Date.now()); - - // end interval when the difference between now and timeFrom is less than or equal to 0 - const continueInterval = shouldEnd ? (timeFrom || now) - now >= 0 : true; - const intervalEnabled = - !!timeFrom && Math.abs(now - (timeFrom || now)) < TimeUnit.ONE_HOUR && continueInterval; - - const formattedTime = useMemo( - () => timeAgo(timeFrom, now, shortedTimeLabel, endLabel, maxTimeUnit), - [timeFrom, now, shortedTimeLabel, endLabel, maxTimeUnit], - ); - - useEffect(() => { - if (!timeFrom || !intervalEnabled) return; - const timeout = setInterval(() => setNow(Date.now()), TimeUnit.ONE_SECOND); - return () => clearTimeout(timeout); - }, [intervalEnabled, timeFrom]); - - return formattedTime; -} - -// TODO - this need a bit of modification to account for multiple display format types -export const timeAgo = ( - epochMilliSecs: number | null | undefined, - timeNow?: number | null, - shortenTimeLabel?: boolean, - endLabel = `< 1 sec`, - maxTimeUnit = TimeUnit.ONE_DAY, -): string => { - if (!epochMilliSecs) return ''; - - timeNow = timeNow ? timeNow : Date.now(); - const dateKeyType = shortenTimeLabel ? 'short' : 'full'; - - let timeUnit: [string, number][]; - let timeCol = Math.abs(timeNow - epochMilliSecs); - - if (timeCol >= maxTimeUnit && maxTimeUnit >= TimeUnit.ONE_DAY) { - timeUnit = [ - [TIME_LABEL.day[dateKeyType], TimeUnit.ONE_DAY], - [TIME_LABEL.hour[dateKeyType], TimeUnit.ONE_HOUR], - ]; - } else if (timeCol >= TimeUnit.ONE_HOUR) { - timeUnit = [ - [TIME_LABEL.hour[dateKeyType], TimeUnit.ONE_HOUR], - [TIME_LABEL.min[dateKeyType], TimeUnit.ONE_MINUTE], - ]; - } else { - timeUnit = [ - [TIME_LABEL.min[dateKeyType], TimeUnit.ONE_MINUTE], - [TIME_LABEL.sec[dateKeyType], TimeUnit.ONE_SECOND], - ]; - } - - const convertAmount = (amount: number, label: string) => { - const spacing = shortenTimeLabel ? '' : ' '; - if (amount > 1) return `${amount}${spacing}${label}${!shortenTimeLabel ? 's' : ''}`; - if (amount === 1) return `${amount}${spacing}${label}`; - return ''; - }; - - const resultArr = timeUnit.map(([label, denom]) => { - const whole = Math.floor(timeCol / denom); - timeCol = timeCol - whole * denom; - return convertAmount(whole, label); - }); - - const result = resultArr.join(' ').trim(); - - return result ? result : endLabel; -}; - -// TODO - Merge with related functions -type Format = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'weekday'; - -export function formatDate(date: Date | number, format?: Format[]): string { - const formatOption = format ?? (['month', 'day', 'hour', 'minute'] as Format[]); - const dateTime = new Date(date); - if (!(dateTime instanceof Date)) return ''; - - const options = { - year: 'numeric', - month: 'short', - day: 'numeric', - hour: 'numeric', - weekday: 'short', - minute: 'numeric', - second: 'numeric', - }; - - const formatOptions = formatOption.reduce((accumulator, current: Format) => { - const responseObj = { - ...accumulator, - ...{ [current]: options[current] }, - }; - return responseObj; - }, {}); - - return new Intl.DateTimeFormat('en-US', formatOptions).format(dateTime); -} diff --git a/apps/core/src/hooks/useTokenPrice.ts b/apps/core/src/hooks/useTokenPrice.ts deleted file mode 100644 index 6db78523475a9..0000000000000 --- a/apps/core/src/hooks/useTokenPrice.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; - -import { useAppsBackend } from './useAppsBackend'; -import { useCoinMetadata } from './useFormatCoin'; - -type TokenPriceResponse = { price: string | null }; - -export function useTokenPrice(coinType: string) { - const { request } = useAppsBackend(); - return useQuery({ - queryKey: ['apps-backend', 'token-price', coinType], - queryFn: () => request(`cetus/${coinType}`), - - // These values are set to one minute to prevent displaying stale data, as token prices can change frequently. - staleTime: 60 * 1000, - gcTime: 60 * 1000, - }); -} - -export function useBalanceInUSD(coinType: string, balance: bigint | string | number) { - const { data: coinMetadata } = useCoinMetadata(coinType); - const { data: tokenPrice } = useTokenPrice(coinType); - if (!tokenPrice || !coinMetadata || !tokenPrice.price) return null; - return new BigNumber(balance.toString()) - .shiftedBy(-1 * coinMetadata.decimals) - .multipliedBy(tokenPrice.price) - .toNumber(); -} diff --git a/apps/core/src/hooks/useTransactionSummary.ts b/apps/core/src/hooks/useTransactionSummary.ts deleted file mode 100644 index 4bceaa214f89a..0000000000000 --- a/apps/core/src/hooks/useTransactionSummary.ts +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { - DryRunTransactionBlockResponse, - type SuiTransactionBlockResponse, -} from '@mysten/sui/client'; -import { useMemo } from 'react'; - -import { getBalanceChangeSummary } from '../utils/transaction/getBalanceChangeSummary'; -import { getGasSummary } from '../utils/transaction/getGasSummary'; -import { getLabel } from '../utils/transaction/getLabel'; -import { - getObjectChangeSummary, - SuiObjectChangeWithDisplay, -} from '../utils/transaction/getObjectChangeSummary'; -import { getObjectDisplayLookup } from '../utils/transaction/getObjectDisplayLookup'; -import { useMultiGetObjects } from './useMultiGetObjects'; - -export function useTransactionSummary({ - transaction, - currentAddress, - recognizedPackagesList, -}: { - transaction?: SuiTransactionBlockResponse | DryRunTransactionBlockResponse; - currentAddress?: string; - recognizedPackagesList: string[]; -}) { - const { objectChanges } = transaction ?? {}; - - const objectIds = objectChanges - ?.map((change) => 'objectId' in change && change.objectId) - .filter(Boolean) as string[]; - - const { data } = useMultiGetObjects(objectIds, { showDisplay: true }); - const lookup = getObjectDisplayLookup(data); - - const objectChangesWithDisplay = useMemo( - () => - [...(objectChanges ?? [])].map((change) => ({ - ...change, - display: 'objectId' in change ? lookup?.get(change.objectId) : null, - })), - [lookup, objectChanges], - ) as SuiObjectChangeWithDisplay[]; - - const summary = useMemo(() => { - if (!transaction) return null; - const objectSummary = getObjectChangeSummary(objectChangesWithDisplay); - const balanceChangeSummary = getBalanceChangeSummary(transaction, recognizedPackagesList); - const gas = getGasSummary(transaction); - - if ('digest' in transaction) { - // Non-dry-run transaction: - return { - gas, - sender: transaction.transaction?.data.sender, - balanceChanges: balanceChangeSummary, - digest: transaction.digest, - label: getLabel(transaction, currentAddress), - objectSummary, - status: transaction.effects?.status.status, - timestamp: transaction.timestampMs, - upgradedSystemPackages: transaction.effects?.mutated?.filter( - ({ owner }) => owner === 'Immutable', - ), - }; - } else { - // Dry run transaction: - return { - gas, - objectSummary, - balanceChanges: balanceChangeSummary, - }; - } - }, [transaction, objectChangesWithDisplay, recognizedPackagesList, currentAddress]); - - return summary; -} diff --git a/apps/core/src/hooks/useZodForm.ts b/apps/core/src/hooks/useZodForm.ts deleted file mode 100644 index ac9307639d336..0000000000000 --- a/apps/core/src/hooks/useZodForm.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; -import type { UseFormProps } from 'react-hook-form'; -import type { TypeOf, ZodSchema } from 'zod'; - -interface UseZodFormProps> extends UseFormProps> { - schema: T; -} - -export const useZodForm = >({ - schema, - ...formConfig -}: UseZodFormProps) => - useForm({ - ...formConfig, - resolver: zodResolver(schema), - }); diff --git a/apps/core/src/index.ts b/apps/core/src/index.ts deleted file mode 100644 index 7a1bd53135de6..0000000000000 --- a/apps/core/src/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './api/SentryHttpTransport'; -export * from './hooks/useFormatCoin'; -export * from './hooks/useTimeAgo'; -export * from './hooks/useGetValidatorsEvents'; -export * from './hooks/useGetValidatorsApy'; -export * from './hooks/nameService'; -export * from './utils/formatAmount'; -export * from './utils/roundFloat'; -export * from './utils/calculateStakeShare'; -export * from './hooks/useGetTransferAmount'; -export * from './hooks/useGetObject'; -export * from './hooks/useGetDynamicFields'; -export * from './utils/formatPercentageDisplay'; -export * from './utils/getRefGasPrice'; -export * from './hooks/useGetTimeBeforeEpochNumber'; -export * from './hooks/useTransactionSummary'; -export * from './utils/transaction'; -export * from './hooks/useOnScreen'; -export * from './hooks/useGetOwnedObjects'; -export * from './hooks/useCopyToClipboard'; -export * from './hooks/useAppsBackend'; -export * from './hooks/useGetCoins'; -export * from './utils/hasDisplayData'; -export * from './hooks/useMultiGetObjects'; -export * from './utils/persistableStorage'; -export * from './hooks/useProductAnalyticsConfig'; -export * from './hooks/useCookieConsentBanner'; -export * from './hooks/useGetKioskContents'; -export * from './hooks/useZodForm'; -export * from './utils/kiosk'; -export * from './hooks/useElementDimensions'; -export * from './hooks/useSuiCoinData'; -export * from './hooks/useLocalStorage'; -export * from './hooks/useGetDelegatedStake'; -export * from './hooks/useTokenPrice'; diff --git a/apps/core/src/utils/calculateStakeShare.ts b/apps/core/src/utils/calculateStakeShare.ts deleted file mode 100644 index e213446097326..0000000000000 --- a/apps/core/src/utils/calculateStakeShare.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import BigNumber from 'bignumber.js'; - -export const calculateStakeShare = ( - validatorStake: bigint, - totalStake: bigint, - decimalPlaces = 2, -) => { - const bn = new BigNumber(validatorStake.toString()); - const bd = new BigNumber(totalStake.toString()); - const percentage = bn.div(bd).multipliedBy(100).decimalPlaces(decimalPlaces).toNumber(); - return percentage; -}; diff --git a/apps/core/src/utils/chunkArray.ts b/apps/core/src/utils/chunkArray.ts deleted file mode 100644 index c166bf82199a5..0000000000000 --- a/apps/core/src/utils/chunkArray.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export function chunkArray(arr: T[], chunkSize: number) { - return Array.from({ length: Math.ceil(arr.length / chunkSize) }, (_, i) => - arr.slice(i * chunkSize, (i + 1) * chunkSize), - ); -} diff --git a/apps/core/src/utils/formatAmount.ts b/apps/core/src/utils/formatAmount.ts deleted file mode 100644 index 30cb39aa6dc75..0000000000000 --- a/apps/core/src/utils/formatAmount.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import BigNumber from 'bignumber.js'; - -export function formatAmountParts(amount?: BigNumber | bigint | number | string | null) { - if (typeof amount === 'undefined' || amount === null) { - return ['--']; - } - - let postfix = ''; - let bn = new BigNumber(amount.toString()); - const bnAbs = bn.abs(); - - // use absolute value to determine the postfix - if (bnAbs.gte(1_000_000_000)) { - bn = bn.shiftedBy(-9); - postfix = 'B'; - } else if (bnAbs.gte(1_000_000)) { - bn = bn.shiftedBy(-6); - postfix = 'M'; - } else if (bnAbs.gte(10_000)) { - bn = bn.shiftedBy(-3); - postfix = 'K'; - } - - if (bnAbs.gte(1)) { - bn = bn.decimalPlaces(2, BigNumber.ROUND_DOWN); - } - - return [bn.toFormat(), postfix]; -} - -export function formatAmount(...args: Parameters) { - return formatAmountParts(...args) - .filter(Boolean) - .join(' '); -} diff --git a/apps/core/src/utils/formatPercentageDisplay.ts b/apps/core/src/utils/formatPercentageDisplay.ts deleted file mode 100644 index 96ef36a831d15..0000000000000 --- a/apps/core/src/utils/formatPercentageDisplay.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -// For unavailable %, return '--' else return the APY number -export function formatPercentageDisplay( - value: number | null, - nullDisplay = '--', - isApyApprox = false, -) { - return value === null ? nullDisplay : `${isApyApprox ? '~' : ''}${value}%`; -} diff --git a/apps/core/src/utils/getRefGasPrice.ts b/apps/core/src/utils/getRefGasPrice.ts deleted file mode 100644 index f20f82b87ad43..0000000000000 --- a/apps/core/src/utils/getRefGasPrice.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { SuiValidatorSummary } from '@mysten/sui/client'; - -import { calculateStakeShare } from './calculateStakeShare'; - -const REF_THRESHOLD = 66.67; - -/** - * Util to get the Reference Gas Price from a list of validators - * 1. Sort validators by gas price - * 2. Add up stake share from low to high, until reaching REF_THRESHOLD - * 3. Return the gas price of the last validator that was added to the sum - */ -export function getRefGasPrice(validators?: SuiValidatorSummary[]) { - if (!validators?.length) { - return BigInt(0); - } - - const sortedByGasPrice = [...validators].sort((a, b) => { - const aGasPrice = BigInt(a.gasPrice); - const bGasPrice = BigInt(b.gasPrice); - - if (aGasPrice < bGasPrice) { - return -1; - } - - if (aGasPrice > bGasPrice) { - return 1; - } - - return 0; - }); - - const totalStaked = validators.reduce( - (acc, cur) => acc + BigInt(cur.stakingPoolSuiBalance), - BigInt(0), - ); - - let sumOfStakes = 0; - let result = '0'; - - for (let i = 0; i < sortedByGasPrice.length; i++) { - const validator = sortedByGasPrice[i]; - const stake = BigInt(validator?.stakingPoolSuiBalance); - - const stakeShare = calculateStakeShare(stake, totalStaked); - - sumOfStakes += stakeShare; - - if (sumOfStakes >= REF_THRESHOLD) { - result = validator.gasPrice; - break; - } - } - - return BigInt(result); -} diff --git a/apps/core/src/utils/hasDisplayData.ts b/apps/core/src/utils/hasDisplayData.ts deleted file mode 100644 index 02e944e25c353..0000000000000 --- a/apps/core/src/utils/hasDisplayData.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { SuiObjectResponse } from '@mysten/sui/client'; - -export const hasDisplayData = (obj: SuiObjectResponse) => !!obj.data?.display?.data; diff --git a/apps/core/src/utils/kiosk.ts b/apps/core/src/utils/kiosk.ts deleted file mode 100644 index a828d15019cf9..0000000000000 --- a/apps/core/src/utils/kiosk.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { KIOSK_OWNER_CAP, Network, PERSONAL_KIOSK_RULE_ADDRESS } from '@mysten/kiosk'; -import { SuiObjectData, SuiObjectResponse } from '@mysten/sui/client'; - -export const ORIGINBYTE_KIOSK_MODULE = - '0x95a441d389b07437d00dd07e0b6f05f513d7659b13fd7c5d3923c7d9d847199b::ob_kiosk'; - -export const ORIGINBYTE_KIOSK_OWNER_TOKEN = `${ORIGINBYTE_KIOSK_MODULE}::OwnerToken`; - -export function isKioskOwnerToken( - network: Network, - object?: SuiObjectResponse | SuiObjectData | null, -) { - if (!object) return false; - const objectData = 'data' in object && object.data ? object.data : (object as SuiObjectData); - return [ - KIOSK_OWNER_CAP, - `${PERSONAL_KIOSK_RULE_ADDRESS[network]}::personal_kiosk::PersonalKioskCap`, - ORIGINBYTE_KIOSK_OWNER_TOKEN, - ].includes(objectData?.type ?? ''); -} - -export function getKioskIdFromOwnerCap(object: SuiObjectResponse | SuiObjectData) { - const objectData = 'data' in object && object.data ? object.data : (object as SuiObjectData); - const fields = - objectData.content?.dataType === 'moveObject' - ? (objectData.content.fields as { - for?: string; - kiosk?: string; - cap?: { fields: { for: string } }; - }) - : null; - return fields?.for ?? fields?.kiosk ?? fields?.cap?.fields.for!; -} diff --git a/apps/core/src/utils/persistableStorage.ts b/apps/core/src/utils/persistableStorage.ts deleted file mode 100644 index 20c497d7d4d58..0000000000000 --- a/apps/core/src/utils/persistableStorage.ts +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { CookieStorage } from '@amplitude/analytics-client-common'; -import { MemoryStorage } from '@amplitude/analytics-core'; -import { CookieStorageOptions, type Storage } from '@amplitude/analytics-types'; - -export const AMP_COOKIE_PREFIX = 'AMP_'; - -/** - * A custom storage mechanism for Amplitude that stores device - * data in memory until we persist the storage to cookies. This - * allows us to collect analytics data in a GDPR-compliant way - * before the user has formally provided consent for us to use - * tracking cookies :) - */ -export class PersistableStorage implements Storage { - #cookieStorage: CookieStorage; - #memoryStorage: MemoryStorage; - #isPersisted: boolean; - - constructor(options?: CookieStorageOptions) { - this.#cookieStorage = new CookieStorage({ - // These are the default options that the Amplitude SDK uses under the hood - expirationDays: 365, - sameSite: 'Lax', - ...options, - }); - this.#memoryStorage = new MemoryStorage(); - this.#isPersisted = this.#getAmplitudeCookies().length > 0; - } - - async isEnabled(): Promise { - return this.#getActiveStorage().isEnabled(); - } - - async get(key: string): Promise { - return this.#getActiveStorage().get(key); - } - - async getRaw(key: string): Promise { - return this.#getActiveStorage().getRaw(key); - } - - async set(key: string, value: T): Promise { - this.#getActiveStorage().set(key, value); - } - - async remove(key: string): Promise { - this.#getActiveStorage().remove(key); - } - - async reset(): Promise { - this.#getActiveStorage().reset(); - this.#removeAmplitudeCookies(); - this.#isPersisted = false; - } - - persist() { - this.#isPersisted = true; - for (const [key, value] of this.#memoryStorage.memoryStorage) { - this.#cookieStorage.set(key, value); - } - } - - #getActiveStorage() { - return this.#isPersisted ? this.#cookieStorage : this.#memoryStorage; - } - - #getAmplitudeCookies() { - return typeof document !== 'undefined' - ? document.cookie.split('; ').filter((cookie) => cookie.startsWith(AMP_COOKIE_PREFIX)) - : []; - } - - #removeAmplitudeCookies() { - const amplitudeCookies = this.#getAmplitudeCookies(); - for (const cookie of amplitudeCookies) { - document.cookie = `${cookie}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`; - } - } -} diff --git a/apps/core/src/utils/roundFloat.ts b/apps/core/src/utils/roundFloat.ts deleted file mode 100644 index 71098f6ed02ee..0000000000000 --- a/apps/core/src/utils/roundFloat.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -const DEFAULT_PRECISION = 2; -export function roundFloat(num: number, precision = DEFAULT_PRECISION) { - return parseFloat(num.toFixed(precision)); -} diff --git a/apps/core/src/utils/transaction/getBalanceChangeSummary.ts b/apps/core/src/utils/transaction/getBalanceChangeSummary.ts deleted file mode 100644 index 51fe8b51067b6..0000000000000 --- a/apps/core/src/utils/transaction/getBalanceChangeSummary.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { - type DryRunTransactionBlockResponse, - type ObjectOwner, - type SuiTransactionBlockResponse, -} from '@mysten/sui/client'; -import { normalizeSuiObjectId, parseStructTag } from '@mysten/sui/utils'; - -export type BalanceChange = { - coinType: string; - amount: string; - recipient?: string; - owner?: string; - unRecognizedToken: boolean; -}; - -export type BalanceChangeByOwner = Record; -export type BalanceChangeSummary = BalanceChangeByOwner | null; - -export function getOwnerAddress(owner: ObjectOwner): string { - if (typeof owner === 'object') { - if ('AddressOwner' in owner) { - return owner.AddressOwner; - } else if ('ObjectOwner' in owner) { - return owner.ObjectOwner; - } else if ('Shared' in owner) { - return 'Shared'; - } - } - return ''; -} - -export const getBalanceChangeSummary = ( - transaction: DryRunTransactionBlockResponse | SuiTransactionBlockResponse, - recognizedPackagesList: string[], -) => { - const { balanceChanges, effects } = transaction; - if (!balanceChanges || !effects) return null; - - const normalizedRecognizedPackages = recognizedPackagesList.map((itm) => - normalizeSuiObjectId(itm), - ); - const balanceChangeByOwner = {}; - return balanceChanges.reduce((acc, balanceChange) => { - const amount = BigInt(balanceChange.amount); - const owner = getOwnerAddress(balanceChange.owner); - - const recipient = balanceChanges.find( - (bc) => balanceChange.coinType === bc.coinType && amount === BigInt(bc.amount) * -1n, - ); - const { address: packageId } = parseStructTag(balanceChange.coinType); - - const recipientAddress = recipient?.owner ? getOwnerAddress(recipient?.owner) : undefined; - - const summary = { - coinType: balanceChange.coinType, - amount: amount.toString(), - recipient: recipientAddress, - owner, - unRecognizedToken: !normalizedRecognizedPackages.includes(packageId), - }; - - acc[owner] = (acc[owner] ?? []).concat(summary); - return acc; - }, balanceChangeByOwner as BalanceChangeByOwner); -}; - -export const getRecognizedUnRecognizedTokenChanges = (changes: BalanceChange[]) => { - const recognizedTokenChanges = []; - const unRecognizedTokenChanges = []; - for (let change of changes) { - if (change.unRecognizedToken) { - unRecognizedTokenChanges.push(change); - } else { - recognizedTokenChanges.push(change); - } - } - return { recognizedTokenChanges, unRecognizedTokenChanges }; -}; diff --git a/apps/core/src/utils/transaction/getGasSummary.ts b/apps/core/src/utils/transaction/getGasSummary.ts deleted file mode 100644 index 4504cd41f30df..0000000000000 --- a/apps/core/src/utils/transaction/getGasSummary.ts +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { - DryRunTransactionBlockResponse, - GasCostSummary, - SuiGasData, - SuiTransactionBlockResponse, - TransactionEffects, -} from '@mysten/sui/client'; - -type Optional = { - [K in keyof T]?: T[K]; -}; - -export type GasSummaryType = - | (GasCostSummary & - Optional & { - totalGas?: string; - owner?: string; - isSponsored: boolean; - gasUsed: GasCostSummary; - }) - | null; - -export function getGasSummary( - transaction: SuiTransactionBlockResponse | DryRunTransactionBlockResponse, -): GasSummaryType { - const { effects } = transaction; - if (!effects) return null; - const totalGas = getTotalGasUsed(effects); - - let sender = 'transaction' in transaction ? transaction.transaction?.data.sender : undefined; - - const gasData = 'transaction' in transaction ? transaction.transaction?.data.gasData : {}; - - const owner = - 'transaction' in transaction - ? transaction.transaction?.data.gasData.owner - : typeof effects.gasObject.owner === 'object' && 'AddressOwner' in effects.gasObject.owner - ? effects.gasObject.owner.AddressOwner - : ''; - - return { - ...effects.gasUsed, - ...gasData, - owner, - totalGas: totalGas?.toString(), - isSponsored: !!owner && !!sender && owner !== sender, - gasUsed: transaction?.effects!.gasUsed, - }; -} - -export function getTotalGasUsed(effects: TransactionEffects): bigint | undefined { - const gasSummary = effects?.gasUsed; - return gasSummary - ? BigInt(gasSummary.computationCost) + - BigInt(gasSummary.storageCost) - - BigInt(gasSummary.storageRebate) - : undefined; -} diff --git a/apps/core/src/utils/transaction/getLabel.ts b/apps/core/src/utils/transaction/getLabel.ts deleted file mode 100644 index 81fd79a6334c9..0000000000000 --- a/apps/core/src/utils/transaction/getLabel.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SuiTransactionBlockResponse } from '@mysten/sui/client'; - -// todo: add more logic for deriving transaction label -export const getLabel = (transaction: SuiTransactionBlockResponse, currentAddress?: string) => { - const isSender = transaction.transaction?.data.sender === currentAddress; - // Rename to "Send" to Transaction - return isSender ? 'Transaction' : 'Receive'; -}; diff --git a/apps/core/src/utils/transaction/getObjectChangeLabel.ts b/apps/core/src/utils/transaction/getObjectChangeLabel.ts deleted file mode 100644 index 308d9808d9049..0000000000000 --- a/apps/core/src/utils/transaction/getObjectChangeLabel.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { SuiObjectChangeTypes } from './types'; - -export const ObjectChangeLabels = { - created: 'Created', - mutated: 'Updated', - transferred: 'Transfer', - published: 'Publish', - deleted: 'Deleted', - wrapped: 'Wrap', -}; - -export function getObjectChangeLabel(type: SuiObjectChangeTypes) { - return ObjectChangeLabels[type]; -} diff --git a/apps/core/src/utils/transaction/getObjectChangeSummary.ts b/apps/core/src/utils/transaction/getObjectChangeSummary.ts deleted file mode 100644 index 91247eb5c1232..0000000000000 --- a/apps/core/src/utils/transaction/getObjectChangeSummary.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { - DisplayFieldsResponse, - SuiObjectChange, - SuiObjectChangeCreated, - SuiObjectChangeDeleted, - SuiObjectChangeMutated, - SuiObjectChangePublished, - SuiObjectChangeTransferred, - SuiObjectChangeWrapped, -} from '@mysten/sui/client'; - -import { groupByOwner } from './groupByOwner'; -import { SuiObjectChangeTypes } from './types'; - -export type WithDisplayFields = T & { display?: DisplayFieldsResponse }; -export type SuiObjectChangeWithDisplay = WithDisplayFields; - -export type ObjectChanges = { - changesWithDisplay: SuiObjectChangeWithDisplay[]; - changes: SuiObjectChange[]; - ownerType: string; -}; -export type ObjectChangesByOwner = Record; - -export type ObjectChangeSummary = { - [K in SuiObjectChangeTypes]: ObjectChangesByOwner; -}; - -export const getObjectChangeSummary = (objectChanges: SuiObjectChangeWithDisplay[]) => { - if (!objectChanges) return null; - - const mutated = objectChanges.filter( - (change) => change.type === 'mutated', - ) as SuiObjectChangeMutated[]; - - const created = objectChanges.filter( - (change) => change.type === 'created', - ) as SuiObjectChangeCreated[]; - - const transferred = objectChanges.filter( - (change) => change.type === 'transferred', - ) as SuiObjectChangeTransferred[]; - - const published = objectChanges.filter( - (change) => change.type === 'published', - ) as SuiObjectChangePublished[]; - - const wrapped = objectChanges.filter( - (change) => change.type === 'wrapped', - ) as SuiObjectChangeWrapped[]; - - const deleted = objectChanges.filter( - (change) => change.type === 'deleted', - ) as SuiObjectChangeDeleted[]; - - return { - transferred: groupByOwner(transferred), - created: groupByOwner(created), - mutated: groupByOwner(mutated), - published: groupByOwner(published), - wrapped: groupByOwner(wrapped), - deleted: groupByOwner(deleted), - }; -}; diff --git a/apps/core/src/utils/transaction/getObjectDisplayLookup.ts b/apps/core/src/utils/transaction/getObjectDisplayLookup.ts deleted file mode 100644 index c7b8166f6b384..0000000000000 --- a/apps/core/src/utils/transaction/getObjectDisplayLookup.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { DisplayFieldsResponse, SuiObjectResponse } from '@mysten/sui/client'; - -import { hasDisplayData } from '../hasDisplayData'; - -export function getObjectDisplayLookup(objects: SuiObjectResponse[] = []) { - const lookup: Map = new Map(); - return objects?.filter(hasDisplayData).reduce((acc, curr) => { - if (curr.data?.objectId) { - acc.set(curr.data.objectId, curr.data.display as DisplayFieldsResponse); - } - return acc; - }, lookup); -} diff --git a/apps/core/src/utils/transaction/getOwnerType.ts b/apps/core/src/utils/transaction/getOwnerType.ts deleted file mode 100644 index 6689e28d6541a..0000000000000 --- a/apps/core/src/utils/transaction/getOwnerType.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiObjectChange } from '@mysten/sui/client'; - -export const getOwnerType = (change: SuiObjectChange) => { - if (!('owner' in change)) return ''; - if (typeof change.owner === 'object') { - if ('AddressOwner' in change.owner) return 'AddressOwner'; - if ('ObjectOwner' in change.owner) return 'ObjectOwner'; - if ('Shared' in change.owner) return 'Shared'; - if ('ConsensusV2' in change.owner) return 'ConsensusV2'; - } - return change.owner; -}; diff --git a/apps/core/src/utils/transaction/groupByOwner.ts b/apps/core/src/utils/transaction/groupByOwner.ts deleted file mode 100644 index d1d164a666314..0000000000000 --- a/apps/core/src/utils/transaction/groupByOwner.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ObjectChangesByOwner, SuiObjectChangeWithDisplay } from './getObjectChangeSummary'; -import { getOwnerType } from './getOwnerType'; - -const getOwner = (change: SuiObjectChangeWithDisplay) => { - // published changes don't have an owner - if ('owner' in change && typeof change.owner === 'object') { - if ('AddressOwner' in change.owner) return change.owner.AddressOwner; - if ('ObjectOwner' in change.owner) return change.owner.ObjectOwner; - if ('Shared' in change.owner) return change.objectId; - if ('ConsensusV2' in change.owner) return change.owner.ConsensusV2.authenticator.SingleOwner; - } - return ''; -}; - -export const groupByOwner = (changes: SuiObjectChangeWithDisplay[]) => - changes.reduce((acc, change) => { - const owner = getOwner(change); - if (!acc[owner]) - acc[owner] = { - changesWithDisplay: [], - changes: [], - ownerType: getOwnerType(change), - }; - - if (change.display?.data) { - acc[owner].changesWithDisplay.push(change); - } else { - acc[owner].changes.push(change); - } - - return acc; - }, {} as ObjectChangesByOwner); diff --git a/apps/core/src/utils/transaction/index.ts b/apps/core/src/utils/transaction/index.ts deleted file mode 100644 index 5a084176b71dd..0000000000000 --- a/apps/core/src/utils/transaction/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './getBalanceChangeSummary'; -export * from './getObjectChangeSummary'; -export * from './getLabel'; -export * from './types'; -export * from './getGasSummary'; -export * from './groupByOwner'; -export * from './getOwnerType'; -export * from './getObjectChangeLabel'; diff --git a/apps/core/src/utils/transaction/types.ts b/apps/core/src/utils/transaction/types.ts deleted file mode 100644 index 1efc96e590644..0000000000000 --- a/apps/core/src/utils/transaction/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { BalanceChangeSummary } from './getBalanceChangeSummary'; -import { GasSummaryType } from './getGasSummary'; -import { ObjectChangeSummary } from './getObjectChangeSummary'; - -export type TransactionSummary = { - digest?: string; - sender?: string; - timestamp?: string | null; - balanceChanges: BalanceChangeSummary; - gas?: GasSummaryType; - objectSummary: ObjectChangeSummary | null; -} | null; - -export type SuiObjectChangeTypes = - | 'published' - | 'transferred' - | 'mutated' - | 'deleted' - | 'wrapped' - | 'created'; diff --git a/apps/core/tailwind.config.ts b/apps/core/tailwind.config.ts deleted file mode 100644 index 56466efb30217..0000000000000 --- a/apps/core/tailwind.config.ts +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Config } from 'tailwindcss'; -import colors from 'tailwindcss/colors'; -import { fontFamily } from 'tailwindcss/defaultTheme'; - -/** The minimum line height that text should use to avoid clipping and overflow scrolling */ -const MIN_LINE_HEIGHT = '1.13'; - -export default { - content: ['./src/**/*.{js,jsx,ts,tsx}'], - theme: { - // Overwrite colors to avoid accidental usage of Tailwind colors: - colors: { - white: colors.white, - black: colors.black, - transparent: colors.transparent, - inherit: colors.inherit, - - gray: { - 100: '#182435', - 95: '#2A3645', - 90: '#383F47', - 85: '#5A6573', - 80: '#636870', - 75: '#767A81', - 70: '#898D93', - 65: '#9C9FA4', - 60: '#C3C5C8', - 55: '#D7D8DA', - 50: '#E9EAEB', - 45: '#E3E6E8', - 40: '#F3F6F8', - 35: '#FEFEFE', - }, - - sui: { - DEFAULT: '#6fbcf0', - bright: '#2A38EB', - light: '#E1F3FF', - primaryBlue2023: '#4CA3FF', - lightest: '#F1F8FD', - dark: '#1F6493', - }, - - steel: { - DEFAULT: '#A0B6C3', - dark: '#758F9E', - darker: '#566873', - }, - - issue: { - DEFAULT: '#FF794B', - dark: '#EB5A29', - light: '#FFECE6', - }, - hero: { - DEFAULT: '#0284AD', - dark: '#007195', - darkest: '#15527B', - }, - success: { - DEFAULT: '#2DD7A7', - dark: '#008C65', - light: '#D5F7EE', - }, - warning: { - DEFAULT: '#F2BD24', - dark: '#8D6E15', - light: '#FFF8E2', - }, - headerNav: '#2A4362', - search: { - fill: '#162A43', - }, - offwhite: '#fefefe', - offblack: '#111111', - ebony: '#101828', - avocado: { - 200: '#CBE5BE', - }, - }, - - extend: { - scale: { - '101': '1.01', - }, - // backdrop-blur values that are found in the design: - backdropBlur: { - sm: '8px', - md: '16px', - DEFAULT: '20px', - lg: '24px', - xl: '32px', - }, - colors: { - 'gradient-blue-start': '#589AEA', - 'gradient-blue-end': '#4C75A6', - 'gradients-graph-cards-start': '#D2EBFA', - 'gradients-failure-start': '#FBF0FF', - }, - // Line-heights that are found in the design: - lineHeight: { - 80: '0.8', - 100: '1', - 130: '1.3', - }, - boxShadow: { - xs: '0px 1px 2px rgba(16, 24, 40, 0.05)', - sm: '0px 1px 2px 0px rgba(86, 104, 115, 0.08)', - md: '1px 2px 8px 2px rgba(86, 104, 115, 0.06)', - lg: '0px 0px 44px 0px rgba(86, 104, 115, 0.22)', - DEFAULT: '0px 0px 20px 0px rgba(86, 104, 115, 0.14)', - notification: '0px 0px 20px rgba(29, 55, 87, 0.11)', - moduleOption: - '0px 0px 29px rgba(0, 0, 0, 0.13), 0px 0px 44px rgba(0, 0, 0, 0.15), 0px 0px 0px rgba(0, 0, 0, 0.2)', - blurXl: '0 0 20px 0 rgba(0, 0, 0, 0.3)', - button: '0px 1px 2px rgba(16, 24, 40, 0.05)', - glow: '0 0px 6px 4px rgba(213,247,238,1)', - drop: '0px 0px 10px rgba(111, 188, 240, 0.2)', - 'effect-ui-regular': - '0px 5px 30px 0px rgba(86, 104, 115, 0.20), 0px 0px 0px 1px rgba(86, 104, 115, 0.03)', - panel: '0px 2px 7px 0px rgba(160, 182, 195, 0.32)', - dropdownContent: '0px 1px 2px 0px rgba(21, 82, 123, 0.08)', - 'effect-ui-wallet-content': '0px -5px 20px 5px rgba(111, 188, 240, 0.11)', - }, - fontSize: { - // Text sizes: - body: ['14px', MIN_LINE_HEIGHT], - bodySmall: ['13px', MIN_LINE_HEIGHT], - subtitle: ['12px', MIN_LINE_HEIGHT], - subtitleSmall: ['11px', MIN_LINE_HEIGHT], - subtitleSmallExtra: ['10px', MIN_LINE_HEIGHT], - caption: ['12px', MIN_LINE_HEIGHT], - captionSmall: ['11px', MIN_LINE_HEIGHT], - captionSmallExtra: ['10px', MIN_LINE_HEIGHT], - iconTextLarge: ['48px', MIN_LINE_HEIGHT], - - // Heading sizes: - heading1: ['28px', MIN_LINE_HEIGHT], - heading2: ['24px', MIN_LINE_HEIGHT], - heading3: ['20px', MIN_LINE_HEIGHT], - heading4: ['18px', MIN_LINE_HEIGHT], - heading5: ['17px', MIN_LINE_HEIGHT], - heading6: ['16px', MIN_LINE_HEIGHT], - - // Paragraph sizes: - pHeading6: ['16px', '1.4'], - pBody: ['14px', '1.4'], - pBodySmall: ['13px', '1.4'], - pSubtitle: ['12px', '1.4'], - pSubtitleSmall: ['11px', '1.4'], - }, - fontFamily: { - system: fontFamily.sans, - sans: ['Inter Variable', 'Inter', ...fontFamily.sans], - mono: ['Red Hat Mono Variable', 'Red Hat Mono', ...fontFamily.mono], - }, - keyframes: { - shimmer: { - '0%': { 'background-position': '-1000px 0' }, - '100%': { 'background-position': '1000px 0' }, - }, - }, - animation: { - shimmer: 'shimmer 2s infinite linear', - }, - spacing: { - 1.25: '0.3125rem', - 3.75: '0.9375rem', - 4.5: '1.125rem', - 7.5: '1.875rem', - 17: '4.25rem', - 18: '4.5rem', - 19: '4.75rem', - 50: '12.5rem', - verticalListShort: '13.0625rem', - verticalListLong: '35.6875rem', - 600: '37.5rem', - header: '68px', - }, - height: { - 12.5: '3.125rem', - 31.5: '7.5rem', - 100: '25rem', - 120: '30rem', - 300: '75rem', - coinsAndAssetsContainer: '31.25rem', - }, - maxHeight: { - coinsAndAssetsContainer: '31.25rem', - ownCoinsPanel: '14.375rem', - }, - width: { - 12.5: '3.125rem', - 31.5: '7.5rem', - walletLogo: '4.813rem', - }, - maxWidth: { - 80: '20rem', - }, - minWidth: { - 10: '2.5rem', - 18: '4.5rem', - 44: '11rem', - 50: '12.5rem', - transactionColumn: '31.875rem', - smallThumbNailsViewContainer: '13.125rem', - smallThumbNailsViewContainerMobile: '9.375rem', - coinItemContainer: '15.625rem', - }, - minHeight: { - 14: '3.5rem', - }, - transitionTimingFunction: { - 'ease-in-out-cubic': 'cubic-bezier(0.65, 0, 0.35, 1)', - 'ease-out-cubic': 'cubic-bezier(0.33, 1, 0.68, 1)', - }, - transitionDuration: { - 400: '400ms', - }, - backgroundImage: { - placeholderGradient01: 'linear-gradient(165.96deg, #e6f5ff 10%, #ebecff 95%)', - placeholderShimmer: - 'linear-gradient(90deg, #ecf1f4 -24.18%, rgba(237 242 245 / 40%) 73.61%, #f3f7f9 114.81%, #ecf1f4 114.82%)', - 'gradients-graph-cards': 'linear-gradient(176deg, #D2EBFA 51.68%, #D5F7EE 100%)', - 'gradients-failure': 'linear-gradient(166deg, #FBF0FF 0%, #FFF0F0 100%)', - objectCard: 'linear-gradient(166deg, #F0F9FF 9.97%, #FEF7FF 94.97%)', - }, - rotate: { - 135: '135deg', - }, - borderRadius: { - '2lg': '0.625rem', - }, - aspectRatio: { - square: '1 / 1', - }, - }, - }, - corePlugins: { - aspectRatio: true, - }, - plugins: [ - require('@headlessui/tailwindcss'), - require('@tailwindcss/aspect-ratio'), - require('@tailwindcss/forms')({ - strategy: 'class', - }), - ], -} satisfies Config; diff --git a/apps/core/tsconfig.json b/apps/core/tsconfig.json deleted file mode 100644 index 4f42cca9d14ee..0000000000000 --- a/apps/core/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "es2020", - "module": "esnext", - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noFallthroughCasesInSwitch": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "noEmit": false, - "isolatedModules": true, - "sourceMap": true, - "jsx": "react-jsx" - }, - "include": ["src"], - "exclude": ["node_modules"] -} diff --git a/apps/core/vitest.config.ts b/apps/core/vitest.config.ts deleted file mode 100644 index 0e8929434a787..0000000000000 --- a/apps/core/vitest.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; -import { defineConfig } from 'vite'; - -process.env.VITE_VERCEL_ENV = process.env.VERCEL_ENV || 'development'; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vanillaExtractPlugin()], -}); diff --git a/apps/icons/.prettierignore b/apps/icons/.prettierignore deleted file mode 100644 index 85de9cf93344b..0000000000000 --- a/apps/icons/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -src diff --git a/apps/icons/README.md b/apps/icons/README.md deleted file mode 100644 index a9627e1ac4f2a..0000000000000 --- a/apps/icons/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# `@mysten/icons` - -## Exporting Icons - -1. Clean the project by running `pnpm icons clean:all` from the repo root. -1. Open Figma Icons file. Create a mass export using `cmd` + `shift` + `e`. Save the SVGs to `sui/apps/icons/svgs`. -1. Run `pnpm icons generate` to generate the new icon library. -1. Commit the changes and submit a PR. diff --git a/apps/icons/package.json b/apps/icons/package.json deleted file mode 100644 index 09c0fdee34ff1..0000000000000 --- a/apps/icons/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@mysten/icons", - "main": "src/index.ts", - "private": true, - "sideEffects": false, - "scripts": { - "clean:src": "rimraf src/**", - "clean:svgs": "rimraf svgs/**", - "clean:all": "pnpm clean:src && pnpm clean:svgs", - "generate": "node scripts/preprocess.mjs && svgr --config-file svgrrc.config.js svgs", - "prettier:check": "prettier -c --ignore-unknown .", - "prettier:fix": "prettier -w --ignore-unknown .", - "eslint:check": "eslint --max-warnings=0 .", - "eslint:fix": "pnpm run eslint:check --fix", - "lint": "pnpm run eslint:check && pnpm run prettier:check", - "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix" - }, - "devDependencies": { - "@svgr/cli": "^7.0.0", - "@svgr/core": "^7.0.0", - "@types/react": "^18.3.3", - "react": "^18.3.1", - "rimraf": "^5.0.1", - "typescript": "^5.5.3" - } -} diff --git a/apps/icons/scripts/preprocess.mjs b/apps/icons/scripts/preprocess.mjs deleted file mode 100644 index 8b98e1c1298a6..0000000000000 --- a/apps/icons/scripts/preprocess.mjs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import fs from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const ROOT_DIR = path.join(fileURLToPath(new URL('.', import.meta.url)), '../svgs'); - -async function processDir(dirname) { - const files = await fs.promises.readdir(dirname, { - withFileTypes: true, - }); - - for (const file of files) { - if (file.isFile()) { - await fs.promises.rename( - path.join(dirname, file.name), - path.join(ROOT_DIR, file.name.trim()), - ); - } else if (file.isDirectory()) { - await processDir(path.join(dirname, file.name)); - await fs.promises.rmdir(path.join(dirname, file.name)); - } - } -} - -async function main() { - await processDir(ROOT_DIR); -} - -main().catch(console.error); diff --git a/apps/icons/src/3D32.tsx b/apps/icons/src/3D32.tsx deleted file mode 100644 index f994321fb9f01..0000000000000 --- a/apps/icons/src/3D32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const Svg3D32 = (props: SVGProps) => ( - - - -); -export default Svg3D32; diff --git a/apps/icons/src/Account24.tsx b/apps/icons/src/Account24.tsx deleted file mode 100644 index e918d9f3ab51b..0000000000000 --- a/apps/icons/src/Account24.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAccount24 = (props: SVGProps) => ( - - - -); -export default SvgAccount24; diff --git a/apps/icons/src/Activity32.tsx b/apps/icons/src/Activity32.tsx deleted file mode 100644 index 099db98a1c626..0000000000000 --- a/apps/icons/src/Activity32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgActivity32 = (props: SVGProps) => ( - - - -); -export default SvgActivity32; diff --git a/apps/icons/src/Add16.tsx b/apps/icons/src/Add16.tsx deleted file mode 100644 index 29ee62343c1b2..0000000000000 --- a/apps/icons/src/Add16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAdd16 = (props: SVGProps) => ( - - - -); -export default SvgAdd16; diff --git a/apps/icons/src/Address16.tsx b/apps/icons/src/Address16.tsx deleted file mode 100644 index 47be31c8480c1..0000000000000 --- a/apps/icons/src/Address16.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAddress16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgAddress16; diff --git a/apps/icons/src/Apps24.tsx b/apps/icons/src/Apps24.tsx deleted file mode 100644 index f4a01a76de649..0000000000000 --- a/apps/icons/src/Apps24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgApps24 = (props: SVGProps) => ( - - - -); -export default SvgApps24; diff --git a/apps/icons/src/Apps32.tsx b/apps/icons/src/Apps32.tsx deleted file mode 100644 index 4abdf2ba7f126..0000000000000 --- a/apps/icons/src/Apps32.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgApps32 = (props: SVGProps) => ( - - - -); -export default SvgApps32; diff --git a/apps/icons/src/ArrowBgFill16.tsx b/apps/icons/src/ArrowBgFill16.tsx deleted file mode 100644 index 226e6d127c254..0000000000000 --- a/apps/icons/src/ArrowBgFill16.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowBgFill16 = (props: SVGProps) => ( - - - - -); -export default SvgArrowBgFill16; diff --git a/apps/icons/src/ArrowBottomLeft16.tsx b/apps/icons/src/ArrowBottomLeft16.tsx deleted file mode 100644 index 75645d63484c8..0000000000000 --- a/apps/icons/src/ArrowBottomLeft16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowBottomLeft16 = (props: SVGProps) => ( - - - -); -export default SvgArrowBottomLeft16; diff --git a/apps/icons/src/ArrowDown12.tsx b/apps/icons/src/ArrowDown12.tsx deleted file mode 100644 index da697bdfde318..0000000000000 --- a/apps/icons/src/ArrowDown12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowDown12 = (props: SVGProps) => ( - - - -); -export default SvgArrowDown12; diff --git a/apps/icons/src/ArrowDown16.tsx b/apps/icons/src/ArrowDown16.tsx deleted file mode 100644 index 769e10dfc0ebf..0000000000000 --- a/apps/icons/src/ArrowDown16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowDown16 = (props: SVGProps) => ( - - - -); -export default SvgArrowDown16; diff --git a/apps/icons/src/ArrowLeft12.tsx b/apps/icons/src/ArrowLeft12.tsx deleted file mode 100644 index 31bb4e44ac15a..0000000000000 --- a/apps/icons/src/ArrowLeft12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowLeft12 = (props: SVGProps) => ( - - - -); -export default SvgArrowLeft12; diff --git a/apps/icons/src/ArrowLeft16.tsx b/apps/icons/src/ArrowLeft16.tsx deleted file mode 100644 index fa4574de71521..0000000000000 --- a/apps/icons/src/ArrowLeft16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowLeft16 = (props: SVGProps) => ( - - - -); -export default SvgArrowLeft16; diff --git a/apps/icons/src/ArrowLeft24.tsx b/apps/icons/src/ArrowLeft24.tsx deleted file mode 100644 index 873bb1d42b79f..0000000000000 --- a/apps/icons/src/ArrowLeft24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowLeft24 = (props: SVGProps) => ( - - - -); -export default SvgArrowLeft24; diff --git a/apps/icons/src/ArrowRight12.tsx b/apps/icons/src/ArrowRight12.tsx deleted file mode 100644 index 988a207cd44aa..0000000000000 --- a/apps/icons/src/ArrowRight12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowRight12 = (props: SVGProps) => ( - - - -); -export default SvgArrowRight12; diff --git a/apps/icons/src/ArrowRight16.tsx b/apps/icons/src/ArrowRight16.tsx deleted file mode 100644 index 85dbdffc08c1b..0000000000000 --- a/apps/icons/src/ArrowRight16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowRight16 = (props: SVGProps) => ( - - - -); -export default SvgArrowRight16; diff --git a/apps/icons/src/ArrowShowAndHide16.tsx b/apps/icons/src/ArrowShowAndHide16.tsx deleted file mode 100644 index f132fe703580a..0000000000000 --- a/apps/icons/src/ArrowShowAndHide16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowShowAndHide16 = (props: SVGProps) => ( - - - -); -export default SvgArrowShowAndHide16; diff --git a/apps/icons/src/ArrowShowAndHideDown12.tsx b/apps/icons/src/ArrowShowAndHideDown12.tsx deleted file mode 100644 index d2317fb334c34..0000000000000 --- a/apps/icons/src/ArrowShowAndHideDown12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowShowAndHideDown12 = (props: SVGProps) => ( - - - -); -export default SvgArrowShowAndHideDown12; diff --git a/apps/icons/src/ArrowShowAndHideRight12.tsx b/apps/icons/src/ArrowShowAndHideRight12.tsx deleted file mode 100644 index 9abfbba809688..0000000000000 --- a/apps/icons/src/ArrowShowAndHideRight12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowShowAndHideRight12 = (props: SVGProps) => ( - - - -); -export default SvgArrowShowAndHideRight12; diff --git a/apps/icons/src/ArrowSort12.tsx b/apps/icons/src/ArrowSort12.tsx deleted file mode 100644 index 0a014cc5e77a0..0000000000000 --- a/apps/icons/src/ArrowSort12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowSort12 = (props: SVGProps) => ( - - - -); -export default SvgArrowSort12; diff --git a/apps/icons/src/ArrowSortDown12.tsx b/apps/icons/src/ArrowSortDown12.tsx deleted file mode 100644 index 05e035a63f56a..0000000000000 --- a/apps/icons/src/ArrowSortDown12.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowSortDown12 = (props: SVGProps) => ( - - - - -); -export default SvgArrowSortDown12; diff --git a/apps/icons/src/ArrowSortUp12.tsx b/apps/icons/src/ArrowSortUp12.tsx deleted file mode 100644 index aad40e10fad60..0000000000000 --- a/apps/icons/src/ArrowSortUp12.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowSortUp12 = (props: SVGProps) => ( - - - - -); -export default SvgArrowSortUp12; diff --git a/apps/icons/src/ArrowUp12.tsx b/apps/icons/src/ArrowUp12.tsx deleted file mode 100644 index bb7f5187f1d91..0000000000000 --- a/apps/icons/src/ArrowUp12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowUp12 = (props: SVGProps) => ( - - - -); -export default SvgArrowUp12; diff --git a/apps/icons/src/ArrowUpRight12.tsx b/apps/icons/src/ArrowUpRight12.tsx deleted file mode 100644 index 294ae148750bd..0000000000000 --- a/apps/icons/src/ArrowUpRight12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowUpRight12 = (props: SVGProps) => ( - - - -); -export default SvgArrowUpRight12; diff --git a/apps/icons/src/ArrowUpRight16.tsx b/apps/icons/src/ArrowUpRight16.tsx deleted file mode 100644 index 12ea258830012..0000000000000 --- a/apps/icons/src/ArrowUpRight16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgArrowUpRight16 = (props: SVGProps) => ( - - - -); -export default SvgArrowUpRight16; diff --git a/apps/icons/src/Audio32.tsx b/apps/icons/src/Audio32.tsx deleted file mode 100644 index 25d5044350103..0000000000000 --- a/apps/icons/src/Audio32.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAudio32 = (props: SVGProps) => ( - - - - - -); -export default SvgAudio32; diff --git a/apps/icons/src/AutorefreshPause24.tsx b/apps/icons/src/AutorefreshPause24.tsx deleted file mode 100644 index 4f4a409ce8a97..0000000000000 --- a/apps/icons/src/AutorefreshPause24.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAutorefreshPause24 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgAutorefreshPause24; diff --git a/apps/icons/src/AutorefreshPlay24.tsx b/apps/icons/src/AutorefreshPlay24.tsx deleted file mode 100644 index f120fe39104c4..0000000000000 --- a/apps/icons/src/AutorefreshPlay24.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgAutorefreshPlay24 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgAutorefreshPlay24; diff --git a/apps/icons/src/Buy16.tsx b/apps/icons/src/Buy16.tsx deleted file mode 100644 index 99e31eafb4a8e..0000000000000 --- a/apps/icons/src/Buy16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgBuy16 = (props: SVGProps) => ( - - - -); -export default SvgBuy16; diff --git a/apps/icons/src/Call16.tsx b/apps/icons/src/Call16.tsx deleted file mode 100644 index 8036395eb479d..0000000000000 --- a/apps/icons/src/Call16.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCall16 = (props: SVGProps) => ( - - - - -); -export default SvgCall16; diff --git a/apps/icons/src/ChangeEpoch16.tsx b/apps/icons/src/ChangeEpoch16.tsx deleted file mode 100644 index 12a8861fe0676..0000000000000 --- a/apps/icons/src/ChangeEpoch16.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChangeEpoch16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgChangeEpoch16; diff --git a/apps/icons/src/Check12.tsx b/apps/icons/src/Check12.tsx deleted file mode 100644 index 4e98bac3eb2b9..0000000000000 --- a/apps/icons/src/Check12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheck12 = (props: SVGProps) => ( - - - -); -export default SvgCheck12; diff --git a/apps/icons/src/Check24.tsx b/apps/icons/src/Check24.tsx deleted file mode 100644 index d0038b791ade3..0000000000000 --- a/apps/icons/src/Check24.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheck24 = (props: SVGProps) => ( - - - - -); -export default SvgCheck24; diff --git a/apps/icons/src/Check241.tsx b/apps/icons/src/Check241.tsx deleted file mode 100644 index ac9f90d8c1e98..0000000000000 --- a/apps/icons/src/Check241.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheck241 = (props: SVGProps) => ( - - - -); -export default SvgCheck241; diff --git a/apps/icons/src/Check32.tsx b/apps/icons/src/Check32.tsx deleted file mode 100644 index 31e72c4bfda59..0000000000000 --- a/apps/icons/src/Check32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheck32 = (props: SVGProps) => ( - - - -); -export default SvgCheck32; diff --git a/apps/icons/src/CheckFill12.tsx b/apps/icons/src/CheckFill12.tsx deleted file mode 100644 index a8b516fa23a50..0000000000000 --- a/apps/icons/src/CheckFill12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheckFill12 = (props: SVGProps) => ( - - - -); -export default SvgCheckFill12; diff --git a/apps/icons/src/CheckFill16.tsx b/apps/icons/src/CheckFill16.tsx deleted file mode 100644 index 96fab03529736..0000000000000 --- a/apps/icons/src/CheckFill16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheckFill16 = (props: SVGProps) => ( - - - -); -export default SvgCheckFill16; diff --git a/apps/icons/src/CheckStroke16.tsx b/apps/icons/src/CheckStroke16.tsx deleted file mode 100644 index d0d9da668253f..0000000000000 --- a/apps/icons/src/CheckStroke16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheckStroke16 = (props: SVGProps) => ( - - - -); -export default SvgCheckStroke16; diff --git a/apps/icons/src/CheckStroke24.tsx b/apps/icons/src/CheckStroke24.tsx deleted file mode 100644 index efffc3d570d58..0000000000000 --- a/apps/icons/src/CheckStroke24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCheckStroke24 = (props: SVGProps) => ( - - - -); -export default SvgCheckStroke24; diff --git a/apps/icons/src/ChevronDown12.tsx b/apps/icons/src/ChevronDown12.tsx deleted file mode 100644 index 27b04e1e6e868..0000000000000 --- a/apps/icons/src/ChevronDown12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronDown12 = (props: SVGProps) => ( - - - -); -export default SvgChevronDown12; diff --git a/apps/icons/src/ChevronDown16.tsx b/apps/icons/src/ChevronDown16.tsx deleted file mode 100644 index 0a941a8f0382d..0000000000000 --- a/apps/icons/src/ChevronDown16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronDown16 = (props: SVGProps) => ( - - - -); -export default SvgChevronDown16; diff --git a/apps/icons/src/ChevronDown24.tsx b/apps/icons/src/ChevronDown24.tsx deleted file mode 100644 index a2fbdf21a3ed3..0000000000000 --- a/apps/icons/src/ChevronDown24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronDown24 = (props: SVGProps) => ( - - - -); -export default SvgChevronDown24; diff --git a/apps/icons/src/ChevronLeft12.tsx b/apps/icons/src/ChevronLeft12.tsx deleted file mode 100644 index b184ca008a645..0000000000000 --- a/apps/icons/src/ChevronLeft12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronLeft12 = (props: SVGProps) => ( - - - -); -export default SvgChevronLeft12; diff --git a/apps/icons/src/ChevronLeft16.tsx b/apps/icons/src/ChevronLeft16.tsx deleted file mode 100644 index 003431512e0f8..0000000000000 --- a/apps/icons/src/ChevronLeft16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronLeft16 = (props: SVGProps) => ( - - - -); -export default SvgChevronLeft16; diff --git a/apps/icons/src/ChevronLeft24.tsx b/apps/icons/src/ChevronLeft24.tsx deleted file mode 100644 index 2f79a534aebc6..0000000000000 --- a/apps/icons/src/ChevronLeft24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronLeft24 = (props: SVGProps) => ( - - - -); -export default SvgChevronLeft24; diff --git a/apps/icons/src/ChevronRight12.tsx b/apps/icons/src/ChevronRight12.tsx deleted file mode 100644 index 26cc880318ac2..0000000000000 --- a/apps/icons/src/ChevronRight12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronRight12 = (props: SVGProps) => ( - - - -); -export default SvgChevronRight12; diff --git a/apps/icons/src/ChevronRight16.tsx b/apps/icons/src/ChevronRight16.tsx deleted file mode 100644 index 1dc13aa4d7cf6..0000000000000 --- a/apps/icons/src/ChevronRight16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronRight16 = (props: SVGProps) => ( - - - -); -export default SvgChevronRight16; diff --git a/apps/icons/src/ChevronUp12.tsx b/apps/icons/src/ChevronUp12.tsx deleted file mode 100644 index bde1c4575d0c2..0000000000000 --- a/apps/icons/src/ChevronUp12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronUp12 = (props: SVGProps) => ( - - - -); -export default SvgChevronUp12; diff --git a/apps/icons/src/ChevronUp16.tsx b/apps/icons/src/ChevronUp16.tsx deleted file mode 100644 index d7b63958a5760..0000000000000 --- a/apps/icons/src/ChevronUp16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgChevronUp16 = (props: SVGProps) => ( - - - -); -export default SvgChevronUp16; diff --git a/apps/icons/src/Clipboard16.tsx b/apps/icons/src/Clipboard16.tsx deleted file mode 100644 index cabdec918fd86..0000000000000 --- a/apps/icons/src/Clipboard16.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgClipboard16 = (props: SVGProps) => ( - - - - -); -export default SvgClipboard16; diff --git a/apps/icons/src/Clipboard24.tsx b/apps/icons/src/Clipboard24.tsx deleted file mode 100644 index 69bc477913019..0000000000000 --- a/apps/icons/src/Clipboard24.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgClipboard24 = (props: SVGProps) => ( - - - - -); -export default SvgClipboard24; diff --git a/apps/icons/src/Code16.tsx b/apps/icons/src/Code16.tsx deleted file mode 100644 index b6b50a03ce9bd..0000000000000 --- a/apps/icons/src/Code16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCode16 = (props: SVGProps) => ( - - - -); -export default SvgCode16; diff --git a/apps/icons/src/Coins16.tsx b/apps/icons/src/Coins16.tsx deleted file mode 100644 index 82fde4a1b1e69..0000000000000 --- a/apps/icons/src/Coins16.tsx +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCoins16 = (props: SVGProps) => ( - - - - -); -export default SvgCoins16; diff --git a/apps/icons/src/Coins24.tsx b/apps/icons/src/Coins24.tsx deleted file mode 100644 index 7f3789940f662..0000000000000 --- a/apps/icons/src/Coins24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCoins24 = (props: SVGProps) => ( - - - -); -export default SvgCoins24; diff --git a/apps/icons/src/Copy12.tsx b/apps/icons/src/Copy12.tsx deleted file mode 100644 index 0b49558d4df53..0000000000000 --- a/apps/icons/src/Copy12.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopy12 = (props: SVGProps) => ( - - - -); -export default SvgCopy12; diff --git a/apps/icons/src/Copy16.tsx b/apps/icons/src/Copy16.tsx deleted file mode 100644 index 60bbff0b79675..0000000000000 --- a/apps/icons/src/Copy16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopy16 = (props: SVGProps) => ( - - - -); -export default SvgCopy16; diff --git a/apps/icons/src/Copy18.tsx b/apps/icons/src/Copy18.tsx deleted file mode 100644 index 72f92dbfd163d..0000000000000 --- a/apps/icons/src/Copy18.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopy18 = (props: SVGProps) => ( - - - - -); -export default SvgCopy18; diff --git a/apps/icons/src/Copy24.tsx b/apps/icons/src/Copy24.tsx deleted file mode 100644 index 8acd2936f1790..0000000000000 --- a/apps/icons/src/Copy24.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopy24 = (props: SVGProps) => ( - - - - -); -export default SvgCopy24; diff --git a/apps/icons/src/CopyArchiveDoNotUse16.tsx b/apps/icons/src/CopyArchiveDoNotUse16.tsx deleted file mode 100644 index 32cd2959e9617..0000000000000 --- a/apps/icons/src/CopyArchiveDoNotUse16.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopyArchiveDoNotUse16 = (props: SVGProps) => ( - - - - -); -export default SvgCopyArchiveDoNotUse16; diff --git a/apps/icons/src/CopyArchiveDoNotUse24.tsx b/apps/icons/src/CopyArchiveDoNotUse24.tsx deleted file mode 100644 index 2f90955974eea..0000000000000 --- a/apps/icons/src/CopyArchiveDoNotUse24.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopyArchiveDoNotUse24 = (props: SVGProps) => ( - - - - -); -export default SvgCopyArchiveDoNotUse24; diff --git a/apps/icons/src/CopyNew24.tsx b/apps/icons/src/CopyNew24.tsx deleted file mode 100644 index a3485e3da9dd5..0000000000000 --- a/apps/icons/src/CopyNew24.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgCopyNew24 = (props: SVGProps) => ( - - - - -); -export default SvgCopyNew24; diff --git a/apps/icons/src/Delete16.tsx b/apps/icons/src/Delete16.tsx deleted file mode 100644 index 5a742b95056fa..0000000000000 --- a/apps/icons/src/Delete16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDelete16 = (props: SVGProps) => ( - - - -); -export default SvgDelete16; diff --git a/apps/icons/src/Destake16.tsx b/apps/icons/src/Destake16.tsx deleted file mode 100644 index b4eb896c05ebd..0000000000000 --- a/apps/icons/src/Destake16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDestake16 = (props: SVGProps) => ( - - - -); -export default SvgDestake16; diff --git a/apps/icons/src/Domain24.tsx b/apps/icons/src/Domain24.tsx deleted file mode 100644 index 536912c9febd2..0000000000000 --- a/apps/icons/src/Domain24.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDomain24 = (props: SVGProps) => ( - - - - -); -export default SvgDomain24; diff --git a/apps/icons/src/Domain32.tsx b/apps/icons/src/Domain32.tsx deleted file mode 100644 index 471586ce15bef..0000000000000 --- a/apps/icons/src/Domain32.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDomain32 = (props: SVGProps) => ( - - - - -); -export default SvgDomain32; diff --git a/apps/icons/src/Dot12.tsx b/apps/icons/src/Dot12.tsx deleted file mode 100644 index 9201ede048b18..0000000000000 --- a/apps/icons/src/Dot12.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDot12 = (props: SVGProps) => ( - - - -); -export default SvgDot12; diff --git a/apps/icons/src/Download16.tsx b/apps/icons/src/Download16.tsx deleted file mode 100644 index 4bd20e273d162..0000000000000 --- a/apps/icons/src/Download16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgDownload16 = (props: SVGProps) => ( - - - -); -export default SvgDownload16; diff --git a/apps/icons/src/EyeClose16.tsx b/apps/icons/src/EyeClose16.tsx deleted file mode 100644 index 2a7ba24d73e8c..0000000000000 --- a/apps/icons/src/EyeClose16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgEyeClose16 = (props: SVGProps) => ( - - - -); -export default SvgEyeClose16; diff --git a/apps/icons/src/EyeOpen16.tsx b/apps/icons/src/EyeOpen16.tsx deleted file mode 100644 index 55d85eb49d6c7..0000000000000 --- a/apps/icons/src/EyeOpen16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgEyeOpen16 = (props: SVGProps) => ( - - - -); -export default SvgEyeOpen16; diff --git a/apps/icons/src/Fail32.tsx b/apps/icons/src/Fail32.tsx deleted file mode 100644 index 69863a0d3c1b9..0000000000000 --- a/apps/icons/src/Fail32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgFail32 = (props: SVGProps) => ( - - - -); -export default SvgFail32; diff --git a/apps/icons/src/Filter12.tsx b/apps/icons/src/Filter12.tsx deleted file mode 100644 index 34e08f31568d2..0000000000000 --- a/apps/icons/src/Filter12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgFilter12 = (props: SVGProps) => ( - - - -); -export default SvgFilter12; diff --git a/apps/icons/src/Filter16.tsx b/apps/icons/src/Filter16.tsx deleted file mode 100644 index 5d1cdf82f3b98..0000000000000 --- a/apps/icons/src/Filter16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgFilter16 = (props: SVGProps) => ( - - - -); -export default SvgFilter16; diff --git a/apps/icons/src/Flag16.tsx b/apps/icons/src/Flag16.tsx deleted file mode 100644 index 2896038729f62..0000000000000 --- a/apps/icons/src/Flag16.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgFlag16 = (props: SVGProps) => ( - - - -); -export default SvgFlag16; diff --git a/apps/icons/src/FlagFill16.tsx b/apps/icons/src/FlagFill16.tsx deleted file mode 100644 index 3f06e9cb1e61c..0000000000000 --- a/apps/icons/src/FlagFill16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgFlagFill16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgFlagFill16; diff --git a/apps/icons/src/Globe16.tsx b/apps/icons/src/Globe16.tsx deleted file mode 100644 index 04e3e6145cf71..0000000000000 --- a/apps/icons/src/Globe16.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgGlobe16 = (props: SVGProps) => ( - - - - -); -export default SvgGlobe16; diff --git a/apps/icons/src/HamburgerOpen24.tsx b/apps/icons/src/HamburgerOpen24.tsx deleted file mode 100644 index 747c45e8ea1bb..0000000000000 --- a/apps/icons/src/HamburgerOpen24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgHamburgerOpen24 = (props: SVGProps) => ( - - - -); -export default SvgHamburgerOpen24; diff --git a/apps/icons/src/HamburgerRest16.tsx b/apps/icons/src/HamburgerRest16.tsx deleted file mode 100644 index 7861d4686407f..0000000000000 --- a/apps/icons/src/HamburgerRest16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgHamburgerRest16 = (props: SVGProps) => ( - - - -); -export default SvgHamburgerRest16; diff --git a/apps/icons/src/HamburgerRest24.tsx b/apps/icons/src/HamburgerRest24.tsx deleted file mode 100644 index d228535423c2f..0000000000000 --- a/apps/icons/src/HamburgerRest24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgHamburgerRest24 = (props: SVGProps) => ( - - - -); -export default SvgHamburgerRest24; diff --git a/apps/icons/src/History24.tsx b/apps/icons/src/History24.tsx deleted file mode 100644 index 646652e3e33a3..0000000000000 --- a/apps/icons/src/History24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgHistory24 = (props: SVGProps) => ( - - - -); -export default SvgHistory24; diff --git a/apps/icons/src/History32.tsx b/apps/icons/src/History32.tsx deleted file mode 100644 index 893334e5ebd8d..0000000000000 --- a/apps/icons/src/History32.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgHistory32 = (props: SVGProps) => ( - - - -); -export default SvgHistory32; diff --git a/apps/icons/src/Image16.tsx b/apps/icons/src/Image16.tsx deleted file mode 100644 index 80fc01f1cd715..0000000000000 --- a/apps/icons/src/Image16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgImage16 = (props: SVGProps) => ( - - - -); -export default SvgImage16; diff --git a/apps/icons/src/Image32.tsx b/apps/icons/src/Image32.tsx deleted file mode 100644 index c1a0b84c3b6f1..0000000000000 --- a/apps/icons/src/Image32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgImage32 = (props: SVGProps) => ( - - - -); -export default SvgImage32; diff --git a/apps/icons/src/Info12.tsx b/apps/icons/src/Info12.tsx deleted file mode 100644 index 9ceb5ad4f6d77..0000000000000 --- a/apps/icons/src/Info12.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgInfo12 = (props: SVGProps) => ( - - - -); -export default SvgInfo12; diff --git a/apps/icons/src/Info16.tsx b/apps/icons/src/Info16.tsx deleted file mode 100644 index edfa83ede86da..0000000000000 --- a/apps/icons/src/Info16.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgInfo16 = (props: SVGProps) => ( - - - -); -export default SvgInfo16; diff --git a/apps/icons/src/LedgerLogo17.tsx b/apps/icons/src/LedgerLogo17.tsx deleted file mode 100644 index 456fe3121daa9..0000000000000 --- a/apps/icons/src/LedgerLogo17.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLedgerLogo17 = (props: SVGProps) => ( - - - -); -export default SvgLedgerLogo17; diff --git a/apps/icons/src/LockLocked16.tsx b/apps/icons/src/LockLocked16.tsx deleted file mode 100644 index d27cf090538b9..0000000000000 --- a/apps/icons/src/LockLocked16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLockLocked16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgLockLocked16; diff --git a/apps/icons/src/LockLocked24.tsx b/apps/icons/src/LockLocked24.tsx deleted file mode 100644 index 2467e1e6c633b..0000000000000 --- a/apps/icons/src/LockLocked24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLockLocked24 = (props: SVGProps) => ( - - - -); -export default SvgLockLocked24; diff --git a/apps/icons/src/LockUnlocked16.tsx b/apps/icons/src/LockUnlocked16.tsx deleted file mode 100644 index e9900dc6aa225..0000000000000 --- a/apps/icons/src/LockUnlocked16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLockUnlocked16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgLockUnlocked16; diff --git a/apps/icons/src/LogoGoogle.tsx b/apps/icons/src/LogoGoogle.tsx deleted file mode 100644 index ffe15031c5f52..0000000000000 --- a/apps/icons/src/LogoGoogle.tsx +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLogoGoogle = (props: SVGProps) => ( - - - - - - -); -export default SvgLogoGoogle; diff --git a/apps/icons/src/LogoQredo.tsx b/apps/icons/src/LogoQredo.tsx deleted file mode 100644 index 14d5dcabae625..0000000000000 --- a/apps/icons/src/LogoQredo.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLogoQredo = (props: SVGProps) => ( - - - - - - - - - -); -export default SvgLogoQredo; diff --git a/apps/icons/src/LogoTwitch.tsx b/apps/icons/src/LogoTwitch.tsx deleted file mode 100644 index b41e0121d3aca..0000000000000 --- a/apps/icons/src/LogoTwitch.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLogoTwitch = (props: SVGProps) => ( - - - -); -export default SvgLogoTwitch; diff --git a/apps/icons/src/Logout24.tsx b/apps/icons/src/Logout24.tsx deleted file mode 100644 index 0904c37eff11c..0000000000000 --- a/apps/icons/src/Logout24.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgLogout24 = (props: SVGProps) => ( - - - - -); -export default SvgLogout24; diff --git a/apps/icons/src/MediaPause16.tsx b/apps/icons/src/MediaPause16.tsx deleted file mode 100644 index 3490d6a530f35..0000000000000 --- a/apps/icons/src/MediaPause16.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgMediaPause16 = (props: SVGProps) => ( - - - - -); -export default SvgMediaPause16; diff --git a/apps/icons/src/MediaPlay16.tsx b/apps/icons/src/MediaPlay16.tsx deleted file mode 100644 index aa6158df96e63..0000000000000 --- a/apps/icons/src/MediaPlay16.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgMediaPlay16 = (props: SVGProps) => ( - - - - -); -export default SvgMediaPlay16; diff --git a/apps/icons/src/Modules24.tsx b/apps/icons/src/Modules24.tsx deleted file mode 100644 index 4b59502723fa4..0000000000000 --- a/apps/icons/src/Modules24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgModules24 = (props: SVGProps) => ( - - - -); -export default SvgModules24; diff --git a/apps/icons/src/More24.tsx b/apps/icons/src/More24.tsx deleted file mode 100644 index c525970b6269b..0000000000000 --- a/apps/icons/src/More24.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgMore24 = (props: SVGProps) => ( - - - -); -export default SvgMore24; diff --git a/apps/icons/src/Nft132.tsx b/apps/icons/src/Nft132.tsx deleted file mode 100644 index 6a582c684b183..0000000000000 --- a/apps/icons/src/Nft132.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNft132 = (props: SVGProps) => ( - - - -); -export default SvgNft132; diff --git a/apps/icons/src/Nft16.tsx b/apps/icons/src/Nft16.tsx deleted file mode 100644 index c096cd287e3ff..0000000000000 --- a/apps/icons/src/Nft16.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNft16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgNft16; diff --git a/apps/icons/src/Nft232.tsx b/apps/icons/src/Nft232.tsx deleted file mode 100644 index 3bc938bc950d4..0000000000000 --- a/apps/icons/src/Nft232.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNft232 = (props: SVGProps) => ( - - - -); -export default SvgNft232; diff --git a/apps/icons/src/Nft24.tsx b/apps/icons/src/Nft24.tsx deleted file mode 100644 index 9e1cc2f47ae66..0000000000000 --- a/apps/icons/src/Nft24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNft24 = (props: SVGProps) => ( - - - -); -export default SvgNft24; diff --git a/apps/icons/src/NftType3D24.tsx b/apps/icons/src/NftType3D24.tsx deleted file mode 100644 index 16497bef92a6b..0000000000000 --- a/apps/icons/src/NftType3D24.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNftType3D24 = (props: SVGProps) => ( - - - -); -export default SvgNftType3D24; diff --git a/apps/icons/src/NftTypeAudio24.tsx b/apps/icons/src/NftTypeAudio24.tsx deleted file mode 100644 index 87cad13cc27b5..0000000000000 --- a/apps/icons/src/NftTypeAudio24.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNftTypeAudio24 = (props: SVGProps) => ( - - - - - -); -export default SvgNftTypeAudio24; diff --git a/apps/icons/src/NftTypeImage24.tsx b/apps/icons/src/NftTypeImage24.tsx deleted file mode 100644 index 98f168425e4b2..0000000000000 --- a/apps/icons/src/NftTypeImage24.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNftTypeImage24 = (props: SVGProps) => ( - - - -); -export default SvgNftTypeImage24; diff --git a/apps/icons/src/NftTypeVideo24.tsx b/apps/icons/src/NftTypeVideo24.tsx deleted file mode 100644 index 21f0c373c87c9..0000000000000 --- a/apps/icons/src/NftTypeVideo24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgNftTypeVideo24 = (props: SVGProps) => ( - - - -); -export default SvgNftTypeVideo24; diff --git a/apps/icons/src/ObjectDetailsHeader.tsx b/apps/icons/src/ObjectDetailsHeader.tsx deleted file mode 100644 index 6a31fede993f5..0000000000000 --- a/apps/icons/src/ObjectDetailsHeader.tsx +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgObjectDetailsHeader = (props: SVGProps) => ( - - - - - - - - - -); -export default SvgObjectDetailsHeader; diff --git a/apps/icons/src/Ooo16.tsx b/apps/icons/src/Ooo16.tsx deleted file mode 100644 index 9e744fb463ccc..0000000000000 --- a/apps/icons/src/Ooo16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgOoo16 = (props: SVGProps) => ( - - - -); -export default SvgOoo16; diff --git a/apps/icons/src/Ooo24.tsx b/apps/icons/src/Ooo24.tsx deleted file mode 100644 index bf671a7bea88b..0000000000000 --- a/apps/icons/src/Ooo24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgOoo24 = (props: SVGProps) => ( - - - -); -export default SvgOoo24; diff --git a/apps/icons/src/PaginationFirst24.tsx b/apps/icons/src/PaginationFirst24.tsx deleted file mode 100644 index e8cdd71e63ba2..0000000000000 --- a/apps/icons/src/PaginationFirst24.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPaginationFirst24 = (props: SVGProps) => ( - - - - -); -export default SvgPaginationFirst24; diff --git a/apps/icons/src/PaginationNext24.tsx b/apps/icons/src/PaginationNext24.tsx deleted file mode 100644 index 2c428ae90a3b4..0000000000000 --- a/apps/icons/src/PaginationNext24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPaginationNext24 = (props: SVGProps) => ( - - - -); -export default SvgPaginationNext24; diff --git a/apps/icons/src/PaginationPrev24.tsx b/apps/icons/src/PaginationPrev24.tsx deleted file mode 100644 index c799f3f86a6c3..0000000000000 --- a/apps/icons/src/PaginationPrev24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPaginationPrev24 = (props: SVGProps) => ( - - - -); -export default SvgPaginationPrev24; diff --git a/apps/icons/src/Pin16.tsx b/apps/icons/src/Pin16.tsx deleted file mode 100644 index e8c1a1cb97650..0000000000000 --- a/apps/icons/src/Pin16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPin16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgPin16; diff --git a/apps/icons/src/Plus12.tsx b/apps/icons/src/Plus12.tsx deleted file mode 100644 index 89830655d3ba2..0000000000000 --- a/apps/icons/src/Plus12.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPlus12 = (props: SVGProps) => ( - - - -); -export default SvgPlus12; diff --git a/apps/icons/src/Plus32.tsx b/apps/icons/src/Plus32.tsx deleted file mode 100644 index f30aae3f95fb7..0000000000000 --- a/apps/icons/src/Plus32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPlus32 = (props: SVGProps) => ( - - - -); -export default SvgPlus32; diff --git a/apps/icons/src/Preview12.tsx b/apps/icons/src/Preview12.tsx deleted file mode 100644 index c1cb39a14f6dd..0000000000000 --- a/apps/icons/src/Preview12.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPreview12 = (props: SVGProps) => ( - - - -); -export default SvgPreview12; diff --git a/apps/icons/src/Publish16.tsx b/apps/icons/src/Publish16.tsx deleted file mode 100644 index c27648000cd14..0000000000000 --- a/apps/icons/src/Publish16.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgPublish16 = (props: SVGProps) => ( - - - - - - - - - - - - - - -); -export default SvgPublish16; diff --git a/apps/icons/src/QrCode.tsx b/apps/icons/src/QrCode.tsx deleted file mode 100644 index 78560cbafa3f5..0000000000000 --- a/apps/icons/src/QrCode.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgQrCode = (props: SVGProps) => ( - - - -); -export default SvgQrCode; diff --git a/apps/icons/src/Receive16.tsx b/apps/icons/src/Receive16.tsx deleted file mode 100644 index 6defd5d5e2215..0000000000000 --- a/apps/icons/src/Receive16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgReceive16 = (props: SVGProps) => ( - - - -); -export default SvgReceive16; diff --git a/apps/icons/src/Receive24.tsx b/apps/icons/src/Receive24.tsx deleted file mode 100644 index 92f9cc331094b..0000000000000 --- a/apps/icons/src/Receive24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgReceive24 = (props: SVGProps) => ( - - - -); -export default SvgReceive24; diff --git a/apps/icons/src/Refresh16.tsx b/apps/icons/src/Refresh16.tsx deleted file mode 100644 index 478ac027eefcd..0000000000000 --- a/apps/icons/src/Refresh16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgRefresh16 = (props: SVGProps) => ( - - - -); -export default SvgRefresh16; diff --git a/apps/icons/src/Search16.tsx b/apps/icons/src/Search16.tsx deleted file mode 100644 index 9a166e283f768..0000000000000 --- a/apps/icons/src/Search16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSearch16 = (props: SVGProps) => ( - - - -); -export default SvgSearch16; diff --git a/apps/icons/src/Search24.tsx b/apps/icons/src/Search24.tsx deleted file mode 100644 index 1feb10cc32048..0000000000000 --- a/apps/icons/src/Search24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSearch24 = (props: SVGProps) => ( - - - -); -export default SvgSearch24; diff --git a/apps/icons/src/Send24.tsx b/apps/icons/src/Send24.tsx deleted file mode 100644 index 4194909a079c1..0000000000000 --- a/apps/icons/src/Send24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSend24 = (props: SVGProps) => ( - - - -); -export default SvgSend24; diff --git a/apps/icons/src/SendReceive16.tsx b/apps/icons/src/SendReceive16.tsx deleted file mode 100644 index dadb48102ea9c..0000000000000 --- a/apps/icons/src/SendReceive16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSendReceive16 = (props: SVGProps) => ( - - - -); -export default SvgSendReceive16; diff --git a/apps/icons/src/Sender16.tsx b/apps/icons/src/Sender16.tsx deleted file mode 100644 index 163c4812cc485..0000000000000 --- a/apps/icons/src/Sender16.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSender16 = (props: SVGProps) => ( - - - - - - - - - - - -); -export default SvgSender16; diff --git a/apps/icons/src/Settings16.tsx b/apps/icons/src/Settings16.tsx deleted file mode 100644 index 650ccb321efee..0000000000000 --- a/apps/icons/src/Settings16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSettings16 = (props: SVGProps) => ( - - - -); -export default SvgSettings16; diff --git a/apps/icons/src/Settings24.tsx b/apps/icons/src/Settings24.tsx deleted file mode 100644 index 8ed3d5701e305..0000000000000 --- a/apps/icons/src/Settings24.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSettings24 = (props: SVGProps) => ( - - - -); -export default SvgSettings24; diff --git a/apps/icons/src/Settings32.tsx b/apps/icons/src/Settings32.tsx deleted file mode 100644 index f37f7d1a7365a..0000000000000 --- a/apps/icons/src/Settings32.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSettings32 = (props: SVGProps) => ( - - - - -); -export default SvgSettings32; diff --git a/apps/icons/src/SocialDiscord24.tsx b/apps/icons/src/SocialDiscord24.tsx deleted file mode 100644 index f9dac42c2f933..0000000000000 --- a/apps/icons/src/SocialDiscord24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialDiscord24 = (props: SVGProps) => ( - - - -); -export default SvgSocialDiscord24; diff --git a/apps/icons/src/SocialFacebook24.tsx b/apps/icons/src/SocialFacebook24.tsx deleted file mode 100644 index 010748087ff8b..0000000000000 --- a/apps/icons/src/SocialFacebook24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialFacebook24 = (props: SVGProps) => ( - - - -); -export default SvgSocialFacebook24; diff --git a/apps/icons/src/SocialGithub24.tsx b/apps/icons/src/SocialGithub24.tsx deleted file mode 100644 index 4d5661d1c4884..0000000000000 --- a/apps/icons/src/SocialGithub24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialGithub24 = (props: SVGProps) => ( - - - -); -export default SvgSocialGithub24; diff --git a/apps/icons/src/SocialGoogle24.tsx b/apps/icons/src/SocialGoogle24.tsx deleted file mode 100644 index cb143a0076b10..0000000000000 --- a/apps/icons/src/SocialGoogle24.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialGoogle24 = (props: SVGProps) => ( - - - - - - - -); -export default SvgSocialGoogle24; diff --git a/apps/icons/src/SocialKakao24.tsx b/apps/icons/src/SocialKakao24.tsx deleted file mode 100644 index 6d946d00815d1..0000000000000 --- a/apps/icons/src/SocialKakao24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialKakao24 = (props: SVGProps) => ( - - - -); -export default SvgSocialKakao24; diff --git a/apps/icons/src/SocialLinkedin24.tsx b/apps/icons/src/SocialLinkedin24.tsx deleted file mode 100644 index 3beeea2270993..0000000000000 --- a/apps/icons/src/SocialLinkedin24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialLinkedin24 = (props: SVGProps) => ( - - - -); -export default SvgSocialLinkedin24; diff --git a/apps/icons/src/SocialMedium24.tsx b/apps/icons/src/SocialMedium24.tsx deleted file mode 100644 index 37f2abc87a88d..0000000000000 --- a/apps/icons/src/SocialMedium24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialMedium24 = (props: SVGProps) => ( - - - -); -export default SvgSocialMedium24; diff --git a/apps/icons/src/SocialMicrosoft24.tsx b/apps/icons/src/SocialMicrosoft24.tsx deleted file mode 100644 index 51fee085c4a9f..0000000000000 --- a/apps/icons/src/SocialMicrosoft24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialMicrosoft24 = (props: SVGProps) => ( - - - - - - -); -export default SvgSocialMicrosoft24; diff --git a/apps/icons/src/SocialTwitch24.tsx b/apps/icons/src/SocialTwitch24.tsx deleted file mode 100644 index c0f7c76e8adab..0000000000000 --- a/apps/icons/src/SocialTwitch24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialTwitch24 = (props: SVGProps) => ( - - - -); -export default SvgSocialTwitch24; diff --git a/apps/icons/src/SocialTwitter24.tsx b/apps/icons/src/SocialTwitter24.tsx deleted file mode 100644 index 39a5a3096e766..0000000000000 --- a/apps/icons/src/SocialTwitter24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSocialTwitter24 = (props: SVGProps) => ( - - - -); -export default SvgSocialTwitter24; diff --git a/apps/icons/src/Spinner16.tsx b/apps/icons/src/Spinner16.tsx deleted file mode 100644 index 5284e943fa98b..0000000000000 --- a/apps/icons/src/Spinner16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSpinner16 = (props: SVGProps) => ( - - - -); -export default SvgSpinner16; diff --git a/apps/icons/src/Spinner24.tsx b/apps/icons/src/Spinner24.tsx deleted file mode 100644 index 8a13c7c9f2091..0000000000000 --- a/apps/icons/src/Spinner24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSpinner24 = (props: SVGProps) => ( - - - -); -export default SvgSpinner24; diff --git a/apps/icons/src/Stack16.tsx b/apps/icons/src/Stack16.tsx deleted file mode 100644 index 028b2c6b997b8..0000000000000 --- a/apps/icons/src/Stack16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgStack16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgStack16; diff --git a/apps/icons/src/Stake24.tsx b/apps/icons/src/Stake24.tsx deleted file mode 100644 index 64db245ba3584..0000000000000 --- a/apps/icons/src/Stake24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgStake24 = (props: SVGProps) => ( - - - -); -export default SvgStake24; diff --git a/apps/icons/src/StakeAdd16.tsx b/apps/icons/src/StakeAdd16.tsx deleted file mode 100644 index 23e6414930b67..0000000000000 --- a/apps/icons/src/StakeAdd16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgStakeAdd16 = (props: SVGProps) => ( - - - -); -export default SvgStakeAdd16; diff --git a/apps/icons/src/StakeRemove16.tsx b/apps/icons/src/StakeRemove16.tsx deleted file mode 100644 index ee386cc10a7c2..0000000000000 --- a/apps/icons/src/StakeRemove16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgStakeRemove16 = (props: SVGProps) => ( - - - -); -export default SvgStakeRemove16; diff --git a/apps/icons/src/Staking32.tsx b/apps/icons/src/Staking32.tsx deleted file mode 100644 index d1d2c62bad914..0000000000000 --- a/apps/icons/src/Staking32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgStaking32 = (props: SVGProps) => ( - - - -); -export default SvgStaking32; diff --git a/apps/icons/src/Sui.tsx b/apps/icons/src/Sui.tsx deleted file mode 100644 index 54ba0a49f84b5..0000000000000 --- a/apps/icons/src/Sui.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSui = (props: SVGProps) => ( - - - -); -export default SvgSui; diff --git a/apps/icons/src/SuiCustomRpc.tsx b/apps/icons/src/SuiCustomRpc.tsx deleted file mode 100644 index 28aa5f0cd8726..0000000000000 --- a/apps/icons/src/SuiCustomRpc.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiCustomRpc = (props: SVGProps) => ( - - - -); -export default SvgSuiCustomRpc; diff --git a/apps/icons/src/SuiDevnet.tsx b/apps/icons/src/SuiDevnet.tsx deleted file mode 100644 index 59bccda429f31..0000000000000 --- a/apps/icons/src/SuiDevnet.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiDevnet = (props: SVGProps) => ( - - - -); -export default SvgSuiDevnet; diff --git a/apps/icons/src/SuiLocal.tsx b/apps/icons/src/SuiLocal.tsx deleted file mode 100644 index f59961826df72..0000000000000 --- a/apps/icons/src/SuiLocal.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiLocal = (props: SVGProps) => ( - - - -); -export default SvgSuiLocal; diff --git a/apps/icons/src/SuiLogoTxt.tsx b/apps/icons/src/SuiLogoTxt.tsx deleted file mode 100644 index 88d10ffa6575a..0000000000000 --- a/apps/icons/src/SuiLogoTxt.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiLogoTxt = (props: SVGProps) => ( - - - -); -export default SvgSuiLogoTxt; diff --git a/apps/icons/src/SuiMainnet.tsx b/apps/icons/src/SuiMainnet.tsx deleted file mode 100644 index 56ac7f9673117..0000000000000 --- a/apps/icons/src/SuiMainnet.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiMainnet = (props: SVGProps) => ( - - - -); -export default SvgSuiMainnet; diff --git a/apps/icons/src/SuiTestnet.tsx b/apps/icons/src/SuiTestnet.tsx deleted file mode 100644 index 1d1e79f99709a..0000000000000 --- a/apps/icons/src/SuiTestnet.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiTestnet = (props: SVGProps) => ( - - - -); -export default SvgSuiTestnet; diff --git a/apps/icons/src/SuiTokensStack.tsx b/apps/icons/src/SuiTokensStack.tsx deleted file mode 100644 index 626fe05af28d7..0000000000000 --- a/apps/icons/src/SuiTokensStack.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSuiTokensStack = (props: SVGProps) => ( - - - - - - - - - - - - - - -); -export default SvgSuiTokensStack; diff --git a/apps/icons/src/Support24.tsx b/apps/icons/src/Support24.tsx deleted file mode 100644 index 0fcb1c93d8377..0000000000000 --- a/apps/icons/src/Support24.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSupport24 = (props: SVGProps) => ( - - - -); -export default SvgSupport24; diff --git a/apps/icons/src/Swap16.tsx b/apps/icons/src/Swap16.tsx deleted file mode 100644 index 98447811df434..0000000000000 --- a/apps/icons/src/Swap16.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgSwap16 = (props: SVGProps) => ( - - - - - -); -export default SvgSwap16; diff --git a/apps/icons/src/Tag16.tsx b/apps/icons/src/Tag16.tsx deleted file mode 100644 index e0bf483ee3f23..0000000000000 --- a/apps/icons/src/Tag16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgTag16 = (props: SVGProps) => ( - - - -); -export default SvgTag16; diff --git a/apps/icons/src/ThumbDownFill12.tsx b/apps/icons/src/ThumbDownFill12.tsx deleted file mode 100644 index d1ec9f7c125d1..0000000000000 --- a/apps/icons/src/ThumbDownFill12.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbDownFill12 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgThumbDownFill12; diff --git a/apps/icons/src/ThumbDownFill24.tsx b/apps/icons/src/ThumbDownFill24.tsx deleted file mode 100644 index a1a8176b56259..0000000000000 --- a/apps/icons/src/ThumbDownFill24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbDownFill24 = (props: SVGProps) => ( - - - -); -export default SvgThumbDownFill24; diff --git a/apps/icons/src/ThumbDownFill32.tsx b/apps/icons/src/ThumbDownFill32.tsx deleted file mode 100644 index 70dec5ed9793c..0000000000000 --- a/apps/icons/src/ThumbDownFill32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbDownFill32 = (props: SVGProps) => ( - - - -); -export default SvgThumbDownFill32; diff --git a/apps/icons/src/ThumbDownStroke24.tsx b/apps/icons/src/ThumbDownStroke24.tsx deleted file mode 100644 index a1bf4daacefc5..0000000000000 --- a/apps/icons/src/ThumbDownStroke24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbDownStroke24 = (props: SVGProps) => ( - - - -); -export default SvgThumbDownStroke24; diff --git a/apps/icons/src/ThumbDownStroke32.tsx b/apps/icons/src/ThumbDownStroke32.tsx deleted file mode 100644 index d7c20c8e459c9..0000000000000 --- a/apps/icons/src/ThumbDownStroke32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbDownStroke32 = (props: SVGProps) => ( - - - -); -export default SvgThumbDownStroke32; diff --git a/apps/icons/src/ThumbUpFill12.tsx b/apps/icons/src/ThumbUpFill12.tsx deleted file mode 100644 index 339507a910520..0000000000000 --- a/apps/icons/src/ThumbUpFill12.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbUpFill12 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgThumbUpFill12; diff --git a/apps/icons/src/ThumbUpFill24.tsx b/apps/icons/src/ThumbUpFill24.tsx deleted file mode 100644 index f60a647f93bb0..0000000000000 --- a/apps/icons/src/ThumbUpFill24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbUpFill24 = (props: SVGProps) => ( - - - -); -export default SvgThumbUpFill24; diff --git a/apps/icons/src/ThumbUpFill32.tsx b/apps/icons/src/ThumbUpFill32.tsx deleted file mode 100644 index 4e0d3eaa741a0..0000000000000 --- a/apps/icons/src/ThumbUpFill32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbUpFill32 = (props: SVGProps) => ( - - - -); -export default SvgThumbUpFill32; diff --git a/apps/icons/src/ThumbUpStroke24.tsx b/apps/icons/src/ThumbUpStroke24.tsx deleted file mode 100644 index 6ca366d201801..0000000000000 --- a/apps/icons/src/ThumbUpStroke24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbUpStroke24 = (props: SVGProps) => ( - - - -); -export default SvgThumbUpStroke24; diff --git a/apps/icons/src/ThumbUpStroke32.tsx b/apps/icons/src/ThumbUpStroke32.tsx deleted file mode 100644 index 3478ba3b3e752..0000000000000 --- a/apps/icons/src/ThumbUpStroke32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbUpStroke32 = (props: SVGProps) => ( - - - -); -export default SvgThumbUpStroke32; diff --git a/apps/icons/src/ThumbnailsOnly16.tsx b/apps/icons/src/ThumbnailsOnly16.tsx deleted file mode 100644 index fc313671f6315..0000000000000 --- a/apps/icons/src/ThumbnailsOnly16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgThumbnailsOnly16 = (props: SVGProps) => ( - - - -); -export default SvgThumbnailsOnly16; diff --git a/apps/icons/src/Tokens32.tsx b/apps/icons/src/Tokens32.tsx deleted file mode 100644 index 6461ac76b2f8e..0000000000000 --- a/apps/icons/src/Tokens32.tsx +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgTokens32 = (props: SVGProps) => ( - - - - -); -export default SvgTokens32; diff --git a/apps/icons/src/TransferObject16.tsx b/apps/icons/src/TransferObject16.tsx deleted file mode 100644 index 82801f4d1de59..0000000000000 --- a/apps/icons/src/TransferObject16.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgTransferObject16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgTransferObject16; diff --git a/apps/icons/src/TransferSui16.tsx b/apps/icons/src/TransferSui16.tsx deleted file mode 100644 index 163f8dc432262..0000000000000 --- a/apps/icons/src/TransferSui16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgTransferSui16 = (props: SVGProps) => ( - - - -); -export default SvgTransferSui16; diff --git a/apps/icons/src/Unpin16.tsx b/apps/icons/src/Unpin16.tsx deleted file mode 100644 index 26904d7d5072c..0000000000000 --- a/apps/icons/src/Unpin16.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgUnpin16 = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgUnpin16; diff --git a/apps/icons/src/Unstaked.tsx b/apps/icons/src/Unstaked.tsx deleted file mode 100644 index 6292c3aa3899d..0000000000000 --- a/apps/icons/src/Unstaked.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgUnstaked = (props: SVGProps) => ( - - - - - - - - - - -); -export default SvgUnstaked; diff --git a/apps/icons/src/Version24.tsx b/apps/icons/src/Version24.tsx deleted file mode 100644 index 68cb7a6f303dc..0000000000000 --- a/apps/icons/src/Version24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgVersion24 = (props: SVGProps) => ( - - - -); -export default SvgVersion24; diff --git a/apps/icons/src/Video32.tsx b/apps/icons/src/Video32.tsx deleted file mode 100644 index 9f4346b9ebc8d..0000000000000 --- a/apps/icons/src/Video32.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgVideo32 = (props: SVGProps) => ( - - - -); -export default SvgVideo32; diff --git a/apps/icons/src/ViewList16.tsx b/apps/icons/src/ViewList16.tsx deleted file mode 100644 index 97eb4874787f5..0000000000000 --- a/apps/icons/src/ViewList16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgViewList16 = (props: SVGProps) => ( - - - -); -export default SvgViewList16; diff --git a/apps/icons/src/ViewSmallThumbnails16.tsx b/apps/icons/src/ViewSmallThumbnails16.tsx deleted file mode 100644 index e6f7833195005..0000000000000 --- a/apps/icons/src/ViewSmallThumbnails16.tsx +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgViewSmallThumbnails16 = (props: SVGProps) => ( - - - - - -); -export default SvgViewSmallThumbnails16; diff --git a/apps/icons/src/Wallet24.tsx b/apps/icons/src/Wallet24.tsx deleted file mode 100644 index 11571092cb57b..0000000000000 --- a/apps/icons/src/Wallet24.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWallet24 = (props: SVGProps) => ( - - - -); -export default SvgWallet24; diff --git a/apps/icons/src/Wallet32.tsx b/apps/icons/src/Wallet32.tsx deleted file mode 100644 index 902a3ba9c0ef8..0000000000000 --- a/apps/icons/src/Wallet32.tsx +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWallet32 = (props: SVGProps) => ( - - - - - -); -export default SvgWallet32; diff --git a/apps/icons/src/WalletActionBuy24.tsx b/apps/icons/src/WalletActionBuy24.tsx deleted file mode 100644 index 48c7134f57a35..0000000000000 --- a/apps/icons/src/WalletActionBuy24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWalletActionBuy24 = (props: SVGProps) => ( - - - -); -export default SvgWalletActionBuy24; diff --git a/apps/icons/src/WalletActionSend24.tsx b/apps/icons/src/WalletActionSend24.tsx deleted file mode 100644 index 9edb8cc694daf..0000000000000 --- a/apps/icons/src/WalletActionSend24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWalletActionSend24 = (props: SVGProps) => ( - - - -); -export default SvgWalletActionSend24; diff --git a/apps/icons/src/WalletActionStake24.tsx b/apps/icons/src/WalletActionStake24.tsx deleted file mode 100644 index d4d34f2cf6cac..0000000000000 --- a/apps/icons/src/WalletActionStake24.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWalletActionStake24 = (props: SVGProps) => ( - - - - - - - -); -export default SvgWalletActionStake24; diff --git a/apps/icons/src/WalletActionSwap24.tsx b/apps/icons/src/WalletActionSwap24.tsx deleted file mode 100644 index 9fb72e26d19f6..0000000000000 --- a/apps/icons/src/WalletActionSwap24.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWalletActionSwap24 = (props: SVGProps) => ( - - - -); -export default SvgWalletActionSwap24; diff --git a/apps/icons/src/Warning16.tsx b/apps/icons/src/Warning16.tsx deleted file mode 100644 index c90e7a041fe01..0000000000000 --- a/apps/icons/src/Warning16.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgWarning16 = (props: SVGProps) => ( - - - -); -export default SvgWarning16; diff --git a/apps/icons/src/X12.tsx b/apps/icons/src/X12.tsx deleted file mode 100644 index a23f1e9010f4f..0000000000000 --- a/apps/icons/src/X12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgX12 = (props: SVGProps) => ( - - - -); -export default SvgX12; diff --git a/apps/icons/src/X32.tsx b/apps/icons/src/X32.tsx deleted file mode 100644 index 577998af7d9ab..0000000000000 --- a/apps/icons/src/X32.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgX32 = (props: SVGProps) => ( - - - -); -export default SvgX32; diff --git a/apps/icons/src/XDark24.tsx b/apps/icons/src/XDark24.tsx deleted file mode 100644 index 5827d65721c17..0000000000000 --- a/apps/icons/src/XDark24.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgXDark24 = (props: SVGProps) => ( - - - - -); -export default SvgXDark24; diff --git a/apps/icons/src/XFill12.tsx b/apps/icons/src/XFill12.tsx deleted file mode 100644 index 360bd4cc4711b..0000000000000 --- a/apps/icons/src/XFill12.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgXFill12 = (props: SVGProps) => ( - - - -); -export default SvgXFill12; diff --git a/apps/icons/src/XFill16.tsx b/apps/icons/src/XFill16.tsx deleted file mode 100644 index 5c74da6c0b5e8..0000000000000 --- a/apps/icons/src/XFill16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgXFill16 = (props: SVGProps) => ( - - - -); -export default SvgXFill16; diff --git a/apps/icons/src/XLight24.tsx b/apps/icons/src/XLight24.tsx deleted file mode 100644 index 8c6ecc8ecfd53..0000000000000 --- a/apps/icons/src/XLight24.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgXLight24 = (props: SVGProps) => ( - - - - -); -export default SvgXLight24; diff --git a/apps/icons/src/XStroke16.tsx b/apps/icons/src/XStroke16.tsx deleted file mode 100644 index d3b7e5d04c07e..0000000000000 --- a/apps/icons/src/XStroke16.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { SVGProps } from 'react'; - -const SvgXStroke16 = (props: SVGProps) => ( - - - -); -export default SvgXStroke16; diff --git a/apps/icons/src/index.ts b/apps/icons/src/index.ts deleted file mode 100644 index 1164398e60ac4..0000000000000 --- a/apps/icons/src/index.ts +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -export { default as Svg3D32 } from './3D32'; -export { default as Nft16 } from './Nft16'; -export { default as Nft132 } from './Nft132'; -export { default as Nft24 } from './Nft24'; -export { default as Nft232 } from './Nft232'; -export { default as Account24 } from './Account24'; -export { default as Activity32 } from './Activity32'; -export { default as Add16 } from './Add16'; -export { default as Address16 } from './Address16'; -export { default as Apps24 } from './Apps24'; -export { default as Apps32 } from './Apps32'; -export { default as ArrowBgFill16 } from './ArrowBgFill16'; -export { default as ArrowBottomLeft16 } from './ArrowBottomLeft16'; -export { default as ArrowDown12 } from './ArrowDown12'; -export { default as ArrowDown16 } from './ArrowDown16'; -export { default as ArrowLeft12 } from './ArrowLeft12'; -export { default as ArrowLeft16 } from './ArrowLeft16'; -export { default as ArrowLeft24 } from './ArrowLeft24'; -export { default as ArrowRight12 } from './ArrowRight12'; -export { default as ArrowRight16 } from './ArrowRight16'; -export { default as ArrowShowAndHide16 } from './ArrowShowAndHide16'; -export { default as ArrowShowAndHideDown12 } from './ArrowShowAndHideDown12'; -export { default as ArrowShowAndHideRight12 } from './ArrowShowAndHideRight12'; -export { default as ArrowSort12 } from './ArrowSort12'; -export { default as ArrowSortDown12 } from './ArrowSortDown12'; -export { default as ArrowSortUp12 } from './ArrowSortUp12'; -export { default as ArrowUp12 } from './ArrowUp12'; -export { default as ArrowUpRight12 } from './ArrowUpRight12'; -export { default as ArrowUpRight16 } from './ArrowUpRight16'; -export { default as Audio32 } from './Audio32'; -export { default as AutorefreshPause24 } from './AutorefreshPause24'; -export { default as AutorefreshPlay24 } from './AutorefreshPlay24'; -export { default as Buy16 } from './Buy16'; -export { default as Call16 } from './Call16'; -export { default as ChangeEpoch16 } from './ChangeEpoch16'; -export { default as Check12 } from './Check12'; -export { default as Check241 } from './Check241'; -export { default as Check24 } from './Check24'; -export { default as Check32 } from './Check32'; -export { default as CheckFill12 } from './CheckFill12'; -export { default as CheckFill16 } from './CheckFill16'; -export { default as CheckStroke16 } from './CheckStroke16'; -export { default as CheckStroke24 } from './CheckStroke24'; -export { default as ChevronDown12 } from './ChevronDown12'; -export { default as ChevronDown16 } from './ChevronDown16'; -export { default as ChevronDown24 } from './ChevronDown24'; -export { default as ChevronLeft12 } from './ChevronLeft12'; -export { default as ChevronLeft16 } from './ChevronLeft16'; -export { default as ChevronLeft24 } from './ChevronLeft24'; -export { default as ChevronRight12 } from './ChevronRight12'; -export { default as ChevronRight16 } from './ChevronRight16'; -export { default as ChevronUp12 } from './ChevronUp12'; -export { default as ChevronUp16 } from './ChevronUp16'; -export { default as Clipboard16 } from './Clipboard16'; -export { default as Clipboard24 } from './Clipboard24'; -export { default as Code16 } from './Code16'; -export { default as Coins16 } from './Coins16'; -export { default as Coins24 } from './Coins24'; -export { default as Copy12 } from './Copy12'; -export { default as Copy16 } from './Copy16'; -export { default as Copy18 } from './Copy18'; -export { default as Copy24 } from './Copy24'; -export { default as CopyArchiveDoNotUse16 } from './CopyArchiveDoNotUse16'; -export { default as CopyArchiveDoNotUse24 } from './CopyArchiveDoNotUse24'; -export { default as CopyNew24 } from './CopyNew24'; -export { default as Delete16 } from './Delete16'; -export { default as Destake16 } from './Destake16'; -export { default as Domain24 } from './Domain24'; -export { default as Domain32 } from './Domain32'; -export { default as Dot12 } from './Dot12'; -export { default as Download16 } from './Download16'; -export { default as EyeClose16 } from './EyeClose16'; -export { default as EyeOpen16 } from './EyeOpen16'; -export { default as Fail32 } from './Fail32'; -export { default as Filter12 } from './Filter12'; -export { default as Filter16 } from './Filter16'; -export { default as Flag16 } from './Flag16'; -export { default as FlagFill16 } from './FlagFill16'; -export { default as Globe16 } from './Globe16'; -export { default as HamburgerOpen24 } from './HamburgerOpen24'; -export { default as HamburgerRest16 } from './HamburgerRest16'; -export { default as HamburgerRest24 } from './HamburgerRest24'; -export { default as History24 } from './History24'; -export { default as History32 } from './History32'; -export { default as Image16 } from './Image16'; -export { default as Image32 } from './Image32'; -export { default as Info12 } from './Info12'; -export { default as Info16 } from './Info16'; -export { default as LedgerLogo17 } from './LedgerLogo17'; -export { default as LockLocked16 } from './LockLocked16'; -export { default as LockLocked24 } from './LockLocked24'; -export { default as LockUnlocked16 } from './LockUnlocked16'; -export { default as LogoGoogle } from './LogoGoogle'; -export { default as LogoQredo } from './LogoQredo'; -export { default as LogoTwitch } from './LogoTwitch'; -export { default as Logout24 } from './Logout24'; -export { default as MediaPause16 } from './MediaPause16'; -export { default as MediaPlay16 } from './MediaPlay16'; -export { default as Modules24 } from './Modules24'; -export { default as More24 } from './More24'; -export { default as NftType3D24 } from './NftType3D24'; -export { default as NftTypeAudio24 } from './NftTypeAudio24'; -export { default as NftTypeImage24 } from './NftTypeImage24'; -export { default as NftTypeVideo24 } from './NftTypeVideo24'; -export { default as ObjectDetailsHeader } from './ObjectDetailsHeader'; -export { default as Ooo16 } from './Ooo16'; -export { default as Ooo24 } from './Ooo24'; -export { default as PaginationFirst24 } from './PaginationFirst24'; -export { default as PaginationNext24 } from './PaginationNext24'; -export { default as PaginationPrev24 } from './PaginationPrev24'; -export { default as Pin16 } from './Pin16'; -export { default as Plus12 } from './Plus12'; -export { default as Plus32 } from './Plus32'; -export { default as Preview12 } from './Preview12'; -export { default as Publish16 } from './Publish16'; -export { default as QrCode } from './QrCode'; -export { default as Receive16 } from './Receive16'; -export { default as Receive24 } from './Receive24'; -export { default as Refresh16 } from './Refresh16'; -export { default as Search16 } from './Search16'; -export { default as Search24 } from './Search24'; -export { default as Send24 } from './Send24'; -export { default as SendReceive16 } from './SendReceive16'; -export { default as Sender16 } from './Sender16'; -export { default as Settings16 } from './Settings16'; -export { default as Settings24 } from './Settings24'; -export { default as Settings32 } from './Settings32'; -export { default as SocialDiscord24 } from './SocialDiscord24'; -export { default as SocialFacebook24 } from './SocialFacebook24'; -export { default as SocialGithub24 } from './SocialGithub24'; -export { default as SocialGoogle24 } from './SocialGoogle24'; -export { default as SocialKakao24 } from './SocialKakao24'; -export { default as SocialLinkedin24 } from './SocialLinkedin24'; -export { default as SocialMedium24 } from './SocialMedium24'; -export { default as SocialMicrosoft24 } from './SocialMicrosoft24'; -export { default as SocialTwitch24 } from './SocialTwitch24'; -export { default as SocialTwitter24 } from './SocialTwitter24'; -export { default as Spinner16 } from './Spinner16'; -export { default as Spinner24 } from './Spinner24'; -export { default as Stack16 } from './Stack16'; -export { default as Stake24 } from './Stake24'; -export { default as StakeAdd16 } from './StakeAdd16'; -export { default as StakeRemove16 } from './StakeRemove16'; -export { default as Staking32 } from './Staking32'; -export { default as SuiLogoTxt } from './SuiLogoTxt'; -export { default as Sui } from './Sui'; -export { default as SuiCustomRpc } from './SuiCustomRpc'; -export { default as SuiDevnet } from './SuiDevnet'; -export { default as SuiLocal } from './SuiLocal'; -export { default as SuiMainnet } from './SuiMainnet'; -export { default as SuiTestnet } from './SuiTestnet'; -export { default as SuiTokensStack } from './SuiTokensStack'; -export { default as Support24 } from './Support24'; -export { default as Swap16 } from './Swap16'; -export { default as Tag16 } from './Tag16'; -export { default as ThumbDownFill12 } from './ThumbDownFill12'; -export { default as ThumbDownFill24 } from './ThumbDownFill24'; -export { default as ThumbDownFill32 } from './ThumbDownFill32'; -export { default as ThumbDownStroke24 } from './ThumbDownStroke24'; -export { default as ThumbDownStroke32 } from './ThumbDownStroke32'; -export { default as ThumbUpFill12 } from './ThumbUpFill12'; -export { default as ThumbUpFill24 } from './ThumbUpFill24'; -export { default as ThumbUpFill32 } from './ThumbUpFill32'; -export { default as ThumbUpStroke24 } from './ThumbUpStroke24'; -export { default as ThumbUpStroke32 } from './ThumbUpStroke32'; -export { default as ThumbnailsOnly16 } from './ThumbnailsOnly16'; -export { default as Tokens32 } from './Tokens32'; -export { default as TransferObject16 } from './TransferObject16'; -export { default as TransferSui16 } from './TransferSui16'; -export { default as Unpin16 } from './Unpin16'; -export { default as Unstaked } from './Unstaked'; -export { default as Version24 } from './Version24'; -export { default as Video32 } from './Video32'; -export { default as ViewList16 } from './ViewList16'; -export { default as ViewSmallThumbnails16 } from './ViewSmallThumbnails16'; -export { default as Wallet24 } from './Wallet24'; -export { default as Wallet32 } from './Wallet32'; -export { default as WalletActionBuy24 } from './WalletActionBuy24'; -export { default as WalletActionSend24 } from './WalletActionSend24'; -export { default as WalletActionStake24 } from './WalletActionStake24'; -export { default as WalletActionSwap24 } from './WalletActionSwap24'; -export { default as Warning16 } from './Warning16'; -export { default as X12 } from './X12'; -export { default as X32 } from './X32'; -export { default as XDark24 } from './XDark24'; -export { default as XFill12 } from './XFill12'; -export { default as XFill16 } from './XFill16'; -export { default as XLight24 } from './XLight24'; -export { default as XStroke16 } from './XStroke16'; diff --git a/apps/icons/svgrrc.config.js b/apps/icons/svgrrc.config.js deleted file mode 100644 index deeea46929b2c..0000000000000 --- a/apps/icons/svgrrc.config.js +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -const path = require('path'); - -const COPYRIGHT = ` -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -`; - -/** @type {import('@svgr/core').Config} */ -module.exports = { - // The default parser set by svgr is `babel`, which makes the import sorting plugin fail. - prettierConfig: { - parser: 'babel-ts', - }, - icon: true, - typescript: true, - outDir: './src', - jsxRuntime: 'automatic', - replaceAttrValues: { - '#383F47': 'currentColor', - '#007195': 'currentColor', - }, - indexTemplate(filePaths) { - const exportEntries = filePaths.map((filePath) => { - const basename = path.basename(filePath, path.extname(filePath)); - const exportName = /^\d/.test(basename) ? `Svg${basename}` : basename; - return `export { default as ${exportName} } from './${basename}'`; - }); - return COPYRIGHT + exportEntries.join('\n'); - }, - template(variables, { tpl }) { - const template = tpl` - ${variables.imports}; - - ${variables.interfaces}; - - const ${variables.componentName} = (${variables.props}) => ( - ${variables.jsx} - ); - - ${variables.exports}; - `; - - // Insert the copyright header, attached to the first node: - template[0].leadingComments = [ - { type: 'CommentLine', value: ' Copyright (c) Mysten Labs, Inc.' }, - { type: 'CommentLine', value: ' SPDX-License-Identifier: Apache-2.0' }, - ]; - - return template; - }, -}; diff --git a/apps/icons/svgs/3D_32.svg b/apps/icons/svgs/3D_32.svg deleted file mode 100644 index a30617d4d6b6e..0000000000000 --- a/apps/icons/svgs/3D_32.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/icons/svgs/NFT_16.svg b/apps/icons/svgs/NFT_16.svg deleted file mode 100644 index 06efd04b14a7d..0000000000000 --- a/apps/icons/svgs/NFT_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/NFT_1_32.svg b/apps/icons/svgs/NFT_1_32.svg deleted file mode 100644 index 610f5a51b1d32..0000000000000 --- a/apps/icons/svgs/NFT_1_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/NFT_24.svg b/apps/icons/svgs/NFT_24.svg deleted file mode 100644 index 85a2c463f8911..0000000000000 --- a/apps/icons/svgs/NFT_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/NFT_2_32.svg b/apps/icons/svgs/NFT_2_32.svg deleted file mode 100644 index e826a3693c5a4..0000000000000 --- a/apps/icons/svgs/NFT_2_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/account_24.svg b/apps/icons/svgs/account_24.svg deleted file mode 100644 index 1551b68407206..0000000000000 --- a/apps/icons/svgs/account_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/activity_32.svg b/apps/icons/svgs/activity_32.svg deleted file mode 100644 index 9b257c529d227..0000000000000 --- a/apps/icons/svgs/activity_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/add_16.svg b/apps/icons/svgs/add_16.svg deleted file mode 100644 index 25eea43d701fb..0000000000000 --- a/apps/icons/svgs/add_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/address_16.svg b/apps/icons/svgs/address_16.svg deleted file mode 100644 index 8a5a6509c5001..0000000000000 --- a/apps/icons/svgs/address_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/apps_24.svg b/apps/icons/svgs/apps_24.svg deleted file mode 100644 index f15f6879f1da6..0000000000000 --- a/apps/icons/svgs/apps_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/apps_32.svg b/apps/icons/svgs/apps_32.svg deleted file mode 100644 index 010ae3897745f..0000000000000 --- a/apps/icons/svgs/apps_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_bg_fill_16.svg b/apps/icons/svgs/arrow_bg_fill_16.svg deleted file mode 100644 index 956f2c4164c6c..0000000000000 --- a/apps/icons/svgs/arrow_bg_fill_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_bottom_left_16.svg b/apps/icons/svgs/arrow_bottom_left_16.svg deleted file mode 100644 index 5ddb704daa496..0000000000000 --- a/apps/icons/svgs/arrow_bottom_left_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_down_12.svg b/apps/icons/svgs/arrow_down_12.svg deleted file mode 100644 index 19e8e66e9a6a8..0000000000000 --- a/apps/icons/svgs/arrow_down_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_down_16.svg b/apps/icons/svgs/arrow_down_16.svg deleted file mode 100644 index 9af6ddaad1a0d..0000000000000 --- a/apps/icons/svgs/arrow_down_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_left_12.svg b/apps/icons/svgs/arrow_left_12.svg deleted file mode 100644 index 69a1d37b5ed9c..0000000000000 --- a/apps/icons/svgs/arrow_left_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_left_16.svg b/apps/icons/svgs/arrow_left_16.svg deleted file mode 100644 index 14e53cf6109d6..0000000000000 --- a/apps/icons/svgs/arrow_left_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_left_24.svg b/apps/icons/svgs/arrow_left_24.svg deleted file mode 100644 index 083341ac45e35..0000000000000 --- a/apps/icons/svgs/arrow_left_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_right_12.svg b/apps/icons/svgs/arrow_right_12.svg deleted file mode 100644 index 96f0414f6405c..0000000000000 --- a/apps/icons/svgs/arrow_right_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_right_16.svg b/apps/icons/svgs/arrow_right_16.svg deleted file mode 100644 index 485b583f6d587..0000000000000 --- a/apps/icons/svgs/arrow_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_show_and_hide_16.svg b/apps/icons/svgs/arrow_show_and_hide_16.svg deleted file mode 100644 index cc5f401ad244e..0000000000000 --- a/apps/icons/svgs/arrow_show_and_hide_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_show_and_hide_down_12.svg b/apps/icons/svgs/arrow_show_and_hide_down_12.svg deleted file mode 100644 index 04038a60e76a5..0000000000000 --- a/apps/icons/svgs/arrow_show_and_hide_down_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_show_and_hide_right_12.svg b/apps/icons/svgs/arrow_show_and_hide_right_12.svg deleted file mode 100644 index 7fe8918844ccc..0000000000000 --- a/apps/icons/svgs/arrow_show_and_hide_right_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_sort_12.svg b/apps/icons/svgs/arrow_sort_12.svg deleted file mode 100644 index 5a3f954d3f46e..0000000000000 --- a/apps/icons/svgs/arrow_sort_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_sort_down_12.svg b/apps/icons/svgs/arrow_sort_down_12.svg deleted file mode 100644 index c32c8136398df..0000000000000 --- a/apps/icons/svgs/arrow_sort_down_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_sort_up_12.svg b/apps/icons/svgs/arrow_sort_up_12.svg deleted file mode 100644 index 47de6df5b5185..0000000000000 --- a/apps/icons/svgs/arrow_sort_up_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_up_12.svg b/apps/icons/svgs/arrow_up_12.svg deleted file mode 100644 index 218d09bf2bae8..0000000000000 --- a/apps/icons/svgs/arrow_up_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/arrow_up_right_12.svg b/apps/icons/svgs/arrow_up_right_12.svg deleted file mode 100644 index 69d470b88b0e7..0000000000000 --- a/apps/icons/svgs/arrow_up_right_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/arrow_up_right_16.svg b/apps/icons/svgs/arrow_up_right_16.svg deleted file mode 100644 index dd581709ce8b1..0000000000000 --- a/apps/icons/svgs/arrow_up_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/audio_32.svg b/apps/icons/svgs/audio_32.svg deleted file mode 100644 index d7ca1aac150d0..0000000000000 --- a/apps/icons/svgs/audio_32.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/autorefresh_pause_24.svg b/apps/icons/svgs/autorefresh_pause_24.svg deleted file mode 100644 index e396237b48e92..0000000000000 --- a/apps/icons/svgs/autorefresh_pause_24.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/autorefresh_play_24.svg b/apps/icons/svgs/autorefresh_play_24.svg deleted file mode 100644 index 51762cda3cfbb..0000000000000 --- a/apps/icons/svgs/autorefresh_play_24.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/buy_16.svg b/apps/icons/svgs/buy_16.svg deleted file mode 100644 index a6a8e5b9aa24e..0000000000000 --- a/apps/icons/svgs/buy_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/call_16.svg b/apps/icons/svgs/call_16.svg deleted file mode 100644 index 36ecbd03141bb..0000000000000 --- a/apps/icons/svgs/call_16.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/change_epoch_16.svg b/apps/icons/svgs/change_epoch_16.svg deleted file mode 100644 index 7063cbf7aa1f7..0000000000000 --- a/apps/icons/svgs/change_epoch_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/check_12.svg b/apps/icons/svgs/check_12.svg deleted file mode 100644 index 12941d6d0b724..0000000000000 --- a/apps/icons/svgs/check_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_24-1.svg b/apps/icons/svgs/check_24-1.svg deleted file mode 100644 index 2146b6c3957a8..0000000000000 --- a/apps/icons/svgs/check_24-1.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_24.svg b/apps/icons/svgs/check_24.svg deleted file mode 100644 index 331b095214a4a..0000000000000 --- a/apps/icons/svgs/check_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/check_32.svg b/apps/icons/svgs/check_32.svg deleted file mode 100644 index 2e93c179f0bf8..0000000000000 --- a/apps/icons/svgs/check_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_fill_12.svg b/apps/icons/svgs/check_fill_12.svg deleted file mode 100644 index 956ec9468f2be..0000000000000 --- a/apps/icons/svgs/check_fill_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_fill_16.svg b/apps/icons/svgs/check_fill_16.svg deleted file mode 100644 index 317dcbb215fd7..0000000000000 --- a/apps/icons/svgs/check_fill_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_stroke_16.svg b/apps/icons/svgs/check_stroke_16.svg deleted file mode 100644 index f57c4cf1a6d5a..0000000000000 --- a/apps/icons/svgs/check_stroke_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/check_stroke_24.svg b/apps/icons/svgs/check_stroke_24.svg deleted file mode 100644 index c4b544308d930..0000000000000 --- a/apps/icons/svgs/check_stroke_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_down_12.svg b/apps/icons/svgs/chevron_down_12.svg deleted file mode 100644 index 30d4c45273558..0000000000000 --- a/apps/icons/svgs/chevron_down_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_down_16.svg b/apps/icons/svgs/chevron_down_16.svg deleted file mode 100644 index 9b6fff6d05530..0000000000000 --- a/apps/icons/svgs/chevron_down_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_down_24.svg b/apps/icons/svgs/chevron_down_24.svg deleted file mode 100644 index d5267d842a42e..0000000000000 --- a/apps/icons/svgs/chevron_down_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_left_12.svg b/apps/icons/svgs/chevron_left_12.svg deleted file mode 100644 index 0a346f9f6810d..0000000000000 --- a/apps/icons/svgs/chevron_left_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_left_16.svg b/apps/icons/svgs/chevron_left_16.svg deleted file mode 100644 index 9985e4186d968..0000000000000 --- a/apps/icons/svgs/chevron_left_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_left_24.svg b/apps/icons/svgs/chevron_left_24.svg deleted file mode 100644 index fa04234ed1984..0000000000000 --- a/apps/icons/svgs/chevron_left_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_right_12.svg b/apps/icons/svgs/chevron_right_12.svg deleted file mode 100644 index 314287de2ab7d..0000000000000 --- a/apps/icons/svgs/chevron_right_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_right_16.svg b/apps/icons/svgs/chevron_right_16.svg deleted file mode 100644 index 8ed52116aecff..0000000000000 --- a/apps/icons/svgs/chevron_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_up_12.svg b/apps/icons/svgs/chevron_up_12.svg deleted file mode 100644 index 58fcdd9afbab4..0000000000000 --- a/apps/icons/svgs/chevron_up_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/chevron_up_16.svg b/apps/icons/svgs/chevron_up_16.svg deleted file mode 100644 index a5400f80493de..0000000000000 --- a/apps/icons/svgs/chevron_up_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/clipboard_16.svg b/apps/icons/svgs/clipboard_16.svg deleted file mode 100644 index 0e0b8cbfc54e6..0000000000000 --- a/apps/icons/svgs/clipboard_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/apps/icons/svgs/clipboard_24.svg b/apps/icons/svgs/clipboard_24.svg deleted file mode 100644 index 07006092ed3aa..0000000000000 --- a/apps/icons/svgs/clipboard_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/code_16.svg b/apps/icons/svgs/code_16.svg deleted file mode 100644 index 874f5b2c8414a..0000000000000 --- a/apps/icons/svgs/code_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/coins_16.svg b/apps/icons/svgs/coins_16.svg deleted file mode 100644 index 6be794851561c..0000000000000 --- a/apps/icons/svgs/coins_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/coins_24.svg b/apps/icons/svgs/coins_24.svg deleted file mode 100644 index 541cd6b635089..0000000000000 --- a/apps/icons/svgs/coins_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/copy_12.svg b/apps/icons/svgs/copy_12.svg deleted file mode 100644 index dafab02f4828c..0000000000000 --- a/apps/icons/svgs/copy_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/copy_16.svg b/apps/icons/svgs/copy_16.svg deleted file mode 100644 index a4bb03c3460d7..0000000000000 --- a/apps/icons/svgs/copy_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/copy_18.svg b/apps/icons/svgs/copy_18.svg deleted file mode 100644 index 9f5942e817101..0000000000000 --- a/apps/icons/svgs/copy_18.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/copy_24.svg b/apps/icons/svgs/copy_24.svg deleted file mode 100644 index 3f39e4e178026..0000000000000 --- a/apps/icons/svgs/copy_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/copy_archive_do_not_use_16.svg b/apps/icons/svgs/copy_archive_do_not_use_16.svg deleted file mode 100644 index c6042c9f0314a..0000000000000 --- a/apps/icons/svgs/copy_archive_do_not_use_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/copy_archive_do_not_use_24.svg b/apps/icons/svgs/copy_archive_do_not_use_24.svg deleted file mode 100644 index 8276a0394683d..0000000000000 --- a/apps/icons/svgs/copy_archive_do_not_use_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/copy_new_24.svg b/apps/icons/svgs/copy_new_24.svg deleted file mode 100644 index bf204cd115c95..0000000000000 --- a/apps/icons/svgs/copy_new_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/delete_16.svg b/apps/icons/svgs/delete_16.svg deleted file mode 100644 index 711f82a65a66c..0000000000000 --- a/apps/icons/svgs/delete_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/destake_16.svg b/apps/icons/svgs/destake_16.svg deleted file mode 100644 index 7f55f68a3e2db..0000000000000 --- a/apps/icons/svgs/destake_16.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/domain_24.svg b/apps/icons/svgs/domain_24.svg deleted file mode 100644 index 55be8f5784cc5..0000000000000 --- a/apps/icons/svgs/domain_24.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/domain_32.svg b/apps/icons/svgs/domain_32.svg deleted file mode 100644 index ed6c0ebd514a6..0000000000000 --- a/apps/icons/svgs/domain_32.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/dot_12.svg b/apps/icons/svgs/dot_12.svg deleted file mode 100644 index 53a1921404b9d..0000000000000 --- a/apps/icons/svgs/dot_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/download_16.svg b/apps/icons/svgs/download_16.svg deleted file mode 100644 index 5efc859a9a5e4..0000000000000 --- a/apps/icons/svgs/download_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/eye_close_16.svg b/apps/icons/svgs/eye_close_16.svg deleted file mode 100644 index cef13196cb806..0000000000000 --- a/apps/icons/svgs/eye_close_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/eye_open_16.svg b/apps/icons/svgs/eye_open_16.svg deleted file mode 100644 index 400d0bc3daa44..0000000000000 --- a/apps/icons/svgs/eye_open_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/fail_32.svg b/apps/icons/svgs/fail_32.svg deleted file mode 100644 index 926d034103a4e..0000000000000 --- a/apps/icons/svgs/fail_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/filter_12.svg b/apps/icons/svgs/filter_12.svg deleted file mode 100644 index 14aa7f869331d..0000000000000 --- a/apps/icons/svgs/filter_12.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/filter_16.svg b/apps/icons/svgs/filter_16.svg deleted file mode 100644 index f13916797706b..0000000000000 --- a/apps/icons/svgs/filter_16.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/flag_16.svg b/apps/icons/svgs/flag_16.svg deleted file mode 100644 index 60331df8adba3..0000000000000 --- a/apps/icons/svgs/flag_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/flag_fill_16.svg b/apps/icons/svgs/flag_fill_16.svg deleted file mode 100644 index efccaa015555e..0000000000000 --- a/apps/icons/svgs/flag_fill_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/globe_16.svg b/apps/icons/svgs/globe_16.svg deleted file mode 100644 index 9288b1ee388a4..0000000000000 --- a/apps/icons/svgs/globe_16.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/hamburger_open_24.svg b/apps/icons/svgs/hamburger_open_24.svg deleted file mode 100644 index 0c78df419a2f9..0000000000000 --- a/apps/icons/svgs/hamburger_open_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/hamburger_rest_16.svg b/apps/icons/svgs/hamburger_rest_16.svg deleted file mode 100644 index 840f4f35b1432..0000000000000 --- a/apps/icons/svgs/hamburger_rest_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/hamburger_rest_24.svg b/apps/icons/svgs/hamburger_rest_24.svg deleted file mode 100644 index f647911d080f2..0000000000000 --- a/apps/icons/svgs/hamburger_rest_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/history_24.svg b/apps/icons/svgs/history_24.svg deleted file mode 100644 index adc02a842a1a1..0000000000000 --- a/apps/icons/svgs/history_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/history_32.svg b/apps/icons/svgs/history_32.svg deleted file mode 100644 index 05620d0cafa27..0000000000000 --- a/apps/icons/svgs/history_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/image_16.svg b/apps/icons/svgs/image_16.svg deleted file mode 100644 index bdab14e1f43b6..0000000000000 --- a/apps/icons/svgs/image_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/image_32.svg b/apps/icons/svgs/image_32.svg deleted file mode 100644 index e826a3693c5a4..0000000000000 --- a/apps/icons/svgs/image_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/info_12.svg b/apps/icons/svgs/info_12.svg deleted file mode 100644 index 2ff072987d5e4..0000000000000 --- a/apps/icons/svgs/info_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/info_16.svg b/apps/icons/svgs/info_16.svg deleted file mode 100644 index a97697dfba5b9..0000000000000 --- a/apps/icons/svgs/info_16.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/ledger_logo_17.svg b/apps/icons/svgs/ledger_logo_17.svg deleted file mode 100644 index 2518383f7a104..0000000000000 --- a/apps/icons/svgs/ledger_logo_17.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/lock_locked_16.svg b/apps/icons/svgs/lock_locked_16.svg deleted file mode 100644 index 767268e521db1..0000000000000 --- a/apps/icons/svgs/lock_locked_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/lock_locked_24.svg b/apps/icons/svgs/lock_locked_24.svg deleted file mode 100644 index 59f6d39890bc0..0000000000000 --- a/apps/icons/svgs/lock_locked_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/lock_unlocked_16.svg b/apps/icons/svgs/lock_unlocked_16.svg deleted file mode 100644 index b2b669d394db5..0000000000000 --- a/apps/icons/svgs/lock_unlocked_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/logo_google.svg b/apps/icons/svgs/logo_google.svg deleted file mode 100644 index 4e3933da3bb05..0000000000000 --- a/apps/icons/svgs/logo_google.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/logo_qredo.svg b/apps/icons/svgs/logo_qredo.svg deleted file mode 100644 index 779ab4872fcdc..0000000000000 --- a/apps/icons/svgs/logo_qredo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/apps/icons/svgs/logo_twitch.svg b/apps/icons/svgs/logo_twitch.svg deleted file mode 100644 index d3127a3765412..0000000000000 --- a/apps/icons/svgs/logo_twitch.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/apps/icons/svgs/logout_24.svg b/apps/icons/svgs/logout_24.svg deleted file mode 100644 index 95927a6a16aae..0000000000000 --- a/apps/icons/svgs/logout_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/media_pause_16.svg b/apps/icons/svgs/media_pause_16.svg deleted file mode 100644 index 44b3390249c18..0000000000000 --- a/apps/icons/svgs/media_pause_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/media_play_16.svg b/apps/icons/svgs/media_play_16.svg deleted file mode 100644 index d6e926dcc8a68..0000000000000 --- a/apps/icons/svgs/media_play_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/modules_24.svg b/apps/icons/svgs/modules_24.svg deleted file mode 100644 index 3d49c4dddc295..0000000000000 --- a/apps/icons/svgs/modules_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/more_24.svg b/apps/icons/svgs/more_24.svg deleted file mode 100644 index 6bac840ada63a..0000000000000 --- a/apps/icons/svgs/more_24.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/nft_type_3D_24.svg b/apps/icons/svgs/nft_type_3D_24.svg deleted file mode 100644 index dcf2da58693d1..0000000000000 --- a/apps/icons/svgs/nft_type_3D_24.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/icons/svgs/nft_type_audio_24.svg b/apps/icons/svgs/nft_type_audio_24.svg deleted file mode 100644 index 633f876a5bb86..0000000000000 --- a/apps/icons/svgs/nft_type_audio_24.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/nft_type_image_24.svg b/apps/icons/svgs/nft_type_image_24.svg deleted file mode 100644 index 79b2f535fc722..0000000000000 --- a/apps/icons/svgs/nft_type_image_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/nft_type_video_24.svg b/apps/icons/svgs/nft_type_video_24.svg deleted file mode 100644 index f62e8f299d360..0000000000000 --- a/apps/icons/svgs/nft_type_video_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/object_details_header.svg b/apps/icons/svgs/object_details_header.svg deleted file mode 100644 index 45a508170be59..0000000000000 --- a/apps/icons/svgs/object_details_header.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/apps/icons/svgs/ooo_16.svg b/apps/icons/svgs/ooo_16.svg deleted file mode 100644 index 491847424bd29..0000000000000 --- a/apps/icons/svgs/ooo_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/ooo_24.svg b/apps/icons/svgs/ooo_24.svg deleted file mode 100644 index 760755b4569f5..0000000000000 --- a/apps/icons/svgs/ooo_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/pagination_first_24.svg b/apps/icons/svgs/pagination_first_24.svg deleted file mode 100644 index 09e4608b8479d..0000000000000 --- a/apps/icons/svgs/pagination_first_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/pagination_next_24.svg b/apps/icons/svgs/pagination_next_24.svg deleted file mode 100644 index 3ab974c2089e2..0000000000000 --- a/apps/icons/svgs/pagination_next_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/pagination_prev_24.svg b/apps/icons/svgs/pagination_prev_24.svg deleted file mode 100644 index 9cb5f10ac5f17..0000000000000 --- a/apps/icons/svgs/pagination_prev_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/pin_16.svg b/apps/icons/svgs/pin_16.svg deleted file mode 100644 index 010e645bb9ae0..0000000000000 --- a/apps/icons/svgs/pin_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/plus_12.svg b/apps/icons/svgs/plus_12.svg deleted file mode 100644 index 152682b1ed4ff..0000000000000 --- a/apps/icons/svgs/plus_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/plus_32.svg b/apps/icons/svgs/plus_32.svg deleted file mode 100644 index f681df0da712b..0000000000000 --- a/apps/icons/svgs/plus_32.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/preview_12.svg b/apps/icons/svgs/preview_12.svg deleted file mode 100644 index 0da8ed8e1e4da..0000000000000 --- a/apps/icons/svgs/preview_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/publish_16.svg b/apps/icons/svgs/publish_16.svg deleted file mode 100644 index 2a0c7c4ffbdb9..0000000000000 --- a/apps/icons/svgs/publish_16.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/apps/icons/svgs/qr-code.svg b/apps/icons/svgs/qr-code.svg deleted file mode 100644 index 7579613c87fcc..0000000000000 --- a/apps/icons/svgs/qr-code.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/receive_16.svg b/apps/icons/svgs/receive_16.svg deleted file mode 100644 index b9363bc407bb5..0000000000000 --- a/apps/icons/svgs/receive_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/receive_24.svg b/apps/icons/svgs/receive_24.svg deleted file mode 100644 index 2a6cd14a5a422..0000000000000 --- a/apps/icons/svgs/receive_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/refresh_16.svg b/apps/icons/svgs/refresh_16.svg deleted file mode 100644 index 7b629b75be24b..0000000000000 --- a/apps/icons/svgs/refresh_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/search_16.svg b/apps/icons/svgs/search_16.svg deleted file mode 100644 index 30b3b9c44e653..0000000000000 --- a/apps/icons/svgs/search_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/search_24.svg b/apps/icons/svgs/search_24.svg deleted file mode 100644 index b92a83682afca..0000000000000 --- a/apps/icons/svgs/search_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/send_24.svg b/apps/icons/svgs/send_24.svg deleted file mode 100644 index 263bd60d380c6..0000000000000 --- a/apps/icons/svgs/send_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/send_receive_16.svg b/apps/icons/svgs/send_receive_16.svg deleted file mode 100644 index df1ea8a44a7e0..0000000000000 --- a/apps/icons/svgs/send_receive_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sender_16.svg b/apps/icons/svgs/sender_16.svg deleted file mode 100644 index 81af2c97c6531..0000000000000 --- a/apps/icons/svgs/sender_16.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/apps/icons/svgs/settings_16.svg b/apps/icons/svgs/settings_16.svg deleted file mode 100644 index ef5ccd63ec26c..0000000000000 --- a/apps/icons/svgs/settings_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/settings_24.svg b/apps/icons/svgs/settings_24.svg deleted file mode 100644 index f04c055f1db03..0000000000000 --- a/apps/icons/svgs/settings_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/settings_32.svg b/apps/icons/svgs/settings_32.svg deleted file mode 100644 index 4815e077ba9ee..0000000000000 --- a/apps/icons/svgs/settings_32.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/social_discord_24.svg b/apps/icons/svgs/social_discord_24.svg deleted file mode 100644 index 4e62f0b7f8e72..0000000000000 --- a/apps/icons/svgs/social_discord_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/social_facebook_24.svg b/apps/icons/svgs/social_facebook_24.svg deleted file mode 100644 index e1c98c7585d7c..0000000000000 --- a/apps/icons/svgs/social_facebook_24.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/apps/icons/svgs/social_github_24.svg b/apps/icons/svgs/social_github_24.svg deleted file mode 100644 index 56563158e0037..0000000000000 --- a/apps/icons/svgs/social_github_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/social_google_24.svg b/apps/icons/svgs/social_google_24.svg deleted file mode 100644 index 636e8d5e681f3..0000000000000 --- a/apps/icons/svgs/social_google_24.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/icons/svgs/social_kakao_24.svg b/apps/icons/svgs/social_kakao_24.svg deleted file mode 100644 index b3c5d181b999b..0000000000000 --- a/apps/icons/svgs/social_kakao_24.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/apps/icons/svgs/social_linkedin_24.svg b/apps/icons/svgs/social_linkedin_24.svg deleted file mode 100644 index ba70d0c45e0a8..0000000000000 --- a/apps/icons/svgs/social_linkedin_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/social_medium_24.svg b/apps/icons/svgs/social_medium_24.svg deleted file mode 100644 index a5ca41c11e9e8..0000000000000 --- a/apps/icons/svgs/social_medium_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/social_microsoft_24.svg b/apps/icons/svgs/social_microsoft_24.svg deleted file mode 100644 index 1df88f5d588c5..0000000000000 --- a/apps/icons/svgs/social_microsoft_24.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/social_twitch_24.svg b/apps/icons/svgs/social_twitch_24.svg deleted file mode 100644 index 3971ec66eb30a..0000000000000 --- a/apps/icons/svgs/social_twitch_24.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/icons/svgs/social_twitter_24.svg b/apps/icons/svgs/social_twitter_24.svg deleted file mode 100644 index 20533210e4b1a..0000000000000 --- a/apps/icons/svgs/social_twitter_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/spinner_16.svg b/apps/icons/svgs/spinner_16.svg deleted file mode 100644 index d62279805d4b2..0000000000000 --- a/apps/icons/svgs/spinner_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/spinner_24.svg b/apps/icons/svgs/spinner_24.svg deleted file mode 100644 index aedbdaa1ee1d0..0000000000000 --- a/apps/icons/svgs/spinner_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/stack_16.svg b/apps/icons/svgs/stack_16.svg deleted file mode 100644 index c5fc6e40d5c93..0000000000000 --- a/apps/icons/svgs/stack_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/stake_24.svg b/apps/icons/svgs/stake_24.svg deleted file mode 100644 index 2cc433d6ad708..0000000000000 --- a/apps/icons/svgs/stake_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/stake_add_16.svg b/apps/icons/svgs/stake_add_16.svg deleted file mode 100644 index 2d76fe817bf56..0000000000000 --- a/apps/icons/svgs/stake_add_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/stake_remove_16.svg b/apps/icons/svgs/stake_remove_16.svg deleted file mode 100644 index 2d5c15b3087d8..0000000000000 --- a/apps/icons/svgs/stake_remove_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/staking_32.svg b/apps/icons/svgs/staking_32.svg deleted file mode 100644 index a048eae51494c..0000000000000 --- a/apps/icons/svgs/staking_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui-logo-txt.svg b/apps/icons/svgs/sui-logo-txt.svg deleted file mode 100644 index 28bb79dc83103..0000000000000 --- a/apps/icons/svgs/sui-logo-txt.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/sui.svg b/apps/icons/svgs/sui.svg deleted file mode 100644 index aa334fee92b5c..0000000000000 --- a/apps/icons/svgs/sui.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_customRPC.svg b/apps/icons/svgs/sui_customRPC.svg deleted file mode 100644 index 1ad4806fadbf6..0000000000000 --- a/apps/icons/svgs/sui_customRPC.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_devnet.svg b/apps/icons/svgs/sui_devnet.svg deleted file mode 100644 index 4628aae50dab3..0000000000000 --- a/apps/icons/svgs/sui_devnet.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_local.svg b/apps/icons/svgs/sui_local.svg deleted file mode 100644 index 1ac25d67956c1..0000000000000 --- a/apps/icons/svgs/sui_local.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_mainnet.svg b/apps/icons/svgs/sui_mainnet.svg deleted file mode 100644 index de59d6f0ffe41..0000000000000 --- a/apps/icons/svgs/sui_mainnet.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_testnet.svg b/apps/icons/svgs/sui_testnet.svg deleted file mode 100644 index 8bdbf21cd0b3b..0000000000000 --- a/apps/icons/svgs/sui_testnet.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/sui_tokens_stack.svg b/apps/icons/svgs/sui_tokens_stack.svg deleted file mode 100644 index 1ff9c1e30e532..0000000000000 --- a/apps/icons/svgs/sui_tokens_stack.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/apps/icons/svgs/support_24.svg b/apps/icons/svgs/support_24.svg deleted file mode 100644 index 6b91fb050dd19..0000000000000 --- a/apps/icons/svgs/support_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/swap_16.svg b/apps/icons/svgs/swap_16.svg deleted file mode 100644 index 58298ee7a6dc1..0000000000000 --- a/apps/icons/svgs/swap_16.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/icons/svgs/tag_16.svg b/apps/icons/svgs/tag_16.svg deleted file mode 100644 index 49ca0a6d3d7a1..0000000000000 --- a/apps/icons/svgs/tag_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_down_fill_12.svg b/apps/icons/svgs/thumb_down_fill_12.svg deleted file mode 100644 index 212cdf422bff9..0000000000000 --- a/apps/icons/svgs/thumb_down_fill_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/thumb_down_fill_24.svg b/apps/icons/svgs/thumb_down_fill_24.svg deleted file mode 100644 index 039d7276080d2..0000000000000 --- a/apps/icons/svgs/thumb_down_fill_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_down_fill_32.svg b/apps/icons/svgs/thumb_down_fill_32.svg deleted file mode 100644 index 71f88a554f340..0000000000000 --- a/apps/icons/svgs/thumb_down_fill_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_down_stroke_24.svg b/apps/icons/svgs/thumb_down_stroke_24.svg deleted file mode 100644 index 815d1869b233a..0000000000000 --- a/apps/icons/svgs/thumb_down_stroke_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_down_stroke_32.svg b/apps/icons/svgs/thumb_down_stroke_32.svg deleted file mode 100644 index fbc19f421fbb4..0000000000000 --- a/apps/icons/svgs/thumb_down_stroke_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_up_fill_12.svg b/apps/icons/svgs/thumb_up_fill_12.svg deleted file mode 100644 index 26fc9a1c66991..0000000000000 --- a/apps/icons/svgs/thumb_up_fill_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/thumb_up_fill_24.svg b/apps/icons/svgs/thumb_up_fill_24.svg deleted file mode 100644 index 6c981f9b82cfe..0000000000000 --- a/apps/icons/svgs/thumb_up_fill_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_up_fill_32.svg b/apps/icons/svgs/thumb_up_fill_32.svg deleted file mode 100644 index d8fe53d98de47..0000000000000 --- a/apps/icons/svgs/thumb_up_fill_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_up_stroke_24.svg b/apps/icons/svgs/thumb_up_stroke_24.svg deleted file mode 100644 index 1d84ecdd0961c..0000000000000 --- a/apps/icons/svgs/thumb_up_stroke_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumb_up_stroke_32.svg b/apps/icons/svgs/thumb_up_stroke_32.svg deleted file mode 100644 index 4c2fd8805272a..0000000000000 --- a/apps/icons/svgs/thumb_up_stroke_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/thumbnails_only_16.svg b/apps/icons/svgs/thumbnails_only_16.svg deleted file mode 100644 index 6d33508dcfa7d..0000000000000 --- a/apps/icons/svgs/thumbnails_only_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/tokens_32.svg b/apps/icons/svgs/tokens_32.svg deleted file mode 100644 index ed179d7bfbd2c..0000000000000 --- a/apps/icons/svgs/tokens_32.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/transfer_object_16.svg b/apps/icons/svgs/transfer_object_16.svg deleted file mode 100644 index 5f7d8f34e444c..0000000000000 --- a/apps/icons/svgs/transfer_object_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/transfer_sui_16.svg b/apps/icons/svgs/transfer_sui_16.svg deleted file mode 100644 index aae9839749d98..0000000000000 --- a/apps/icons/svgs/transfer_sui_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/unpin_16.svg b/apps/icons/svgs/unpin_16.svg deleted file mode 100644 index 366a79ca3f7d6..0000000000000 --- a/apps/icons/svgs/unpin_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/unstaked.svg b/apps/icons/svgs/unstaked.svg deleted file mode 100644 index adc412e30bb3f..0000000000000 --- a/apps/icons/svgs/unstaked.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/icons/svgs/version_24.svg b/apps/icons/svgs/version_24.svg deleted file mode 100644 index 0491310454ebd..0000000000000 --- a/apps/icons/svgs/version_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/video_32.svg b/apps/icons/svgs/video_32.svg deleted file mode 100644 index 7d7131830a0e3..0000000000000 --- a/apps/icons/svgs/video_32.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/view_list_16.svg b/apps/icons/svgs/view_list_16.svg deleted file mode 100644 index 636de33dded38..0000000000000 --- a/apps/icons/svgs/view_list_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/view_small_thumbnails_16.svg b/apps/icons/svgs/view_small_thumbnails_16.svg deleted file mode 100644 index ae30ef904fb28..0000000000000 --- a/apps/icons/svgs/view_small_thumbnails_16.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/apps/icons/svgs/wallet_24.svg b/apps/icons/svgs/wallet_24.svg deleted file mode 100644 index d8c1376790ffe..0000000000000 --- a/apps/icons/svgs/wallet_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/wallet_32.svg b/apps/icons/svgs/wallet_32.svg deleted file mode 100644 index d5e21c7798c3a..0000000000000 --- a/apps/icons/svgs/wallet_32.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/icons/svgs/wallet_action_buy_24.svg b/apps/icons/svgs/wallet_action_buy_24.svg deleted file mode 100644 index cf158f3e9465f..0000000000000 --- a/apps/icons/svgs/wallet_action_buy_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/wallet_action_send_24.svg b/apps/icons/svgs/wallet_action_send_24.svg deleted file mode 100644 index b9e554f5bec5c..0000000000000 --- a/apps/icons/svgs/wallet_action_send_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/wallet_action_stake_24.svg b/apps/icons/svgs/wallet_action_stake_24.svg deleted file mode 100644 index 79432b652d6ea..0000000000000 --- a/apps/icons/svgs/wallet_action_stake_24.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/icons/svgs/wallet_action_swap_24.svg b/apps/icons/svgs/wallet_action_swap_24.svg deleted file mode 100644 index b83fd1d1520d3..0000000000000 --- a/apps/icons/svgs/wallet_action_swap_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/warning_16.svg b/apps/icons/svgs/warning_16.svg deleted file mode 100644 index 11520491a3f62..0000000000000 --- a/apps/icons/svgs/warning_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/x_12.svg b/apps/icons/svgs/x_12.svg deleted file mode 100644 index be420466e5049..0000000000000 --- a/apps/icons/svgs/x_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/x_32.svg b/apps/icons/svgs/x_32.svg deleted file mode 100644 index 7236f2cfd57c7..0000000000000 --- a/apps/icons/svgs/x_32.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/x_dark_24.svg b/apps/icons/svgs/x_dark_24.svg deleted file mode 100644 index 2590ea1d6457e..0000000000000 --- a/apps/icons/svgs/x_dark_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/x_fill_12.svg b/apps/icons/svgs/x_fill_12.svg deleted file mode 100644 index 9d3805c177485..0000000000000 --- a/apps/icons/svgs/x_fill_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/x_fill_16.svg b/apps/icons/svgs/x_fill_16.svg deleted file mode 100644 index 5f8e519843719..0000000000000 --- a/apps/icons/svgs/x_fill_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/svgs/x_light_24.svg b/apps/icons/svgs/x_light_24.svg deleted file mode 100644 index 4505a07e6b40d..0000000000000 --- a/apps/icons/svgs/x_light_24.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/icons/svgs/x_stroke_16.svg b/apps/icons/svgs/x_stroke_16.svg deleted file mode 100644 index 66e7c3c4788f8..0000000000000 --- a/apps/icons/svgs/x_stroke_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/icons/tsconfig.json b/apps/icons/tsconfig.json deleted file mode 100644 index 17f8b9acc3fdb..0000000000000 --- a/apps/icons/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "noEmit": true, - "target": "ESNext", - "jsx": "react-jsx", - "module": "ESNext", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true - } -} diff --git a/apps/wallet/.babelrc.json b/apps/wallet/.babelrc.json deleted file mode 100644 index 4ce55a565d28e..0000000000000 --- a/apps/wallet/.babelrc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "sourceType": "unambiguous", - "presets": [ - [ - "@babel/preset-env", - { - "shippedProposals": true, - "loose": true - } - ], - "@babel/preset-typescript" - ], - "plugins": [] -} diff --git a/apps/wallet/.browserslistrc b/apps/wallet/.browserslistrc deleted file mode 100644 index bca338ef86c3c..0000000000000 --- a/apps/wallet/.browserslistrc +++ /dev/null @@ -1 +0,0 @@ -chrome >= 88 diff --git a/apps/wallet/.eslintignore b/apps/wallet/.eslintignore deleted file mode 100644 index a52bd76e906f6..0000000000000 --- a/apps/wallet/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -dist/ -node_modules/ -.next/ -.swc/ -out/ diff --git a/apps/wallet/.gitignore b/apps/wallet/.gitignore deleted file mode 100644 index 472614382323b..0000000000000 --- a/apps/wallet/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -configs/environment/.env -web-ext-artifacts diff --git a/apps/wallet/.prettierignore b/apps/wallet/.prettierignore deleted file mode 100644 index 1b38b62e0defc..0000000000000 --- a/apps/wallet/.prettierignore +++ /dev/null @@ -1,10 +0,0 @@ -dist/ -package-lock.json -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.next/ -.swc/ -out/ -playwright-report/ -CHANGELOG.md diff --git a/apps/wallet/.storybook/main.js b/apps/wallet/.storybook/main.js deleted file mode 100644 index db59c805d84b8..0000000000000 --- a/apps/wallet/.storybook/main.js +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -const { default: getWebpackConfig } = require('../configs/webpack/webpack.config.dev.ts'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const path = require('path'); - -module.exports = { - stories: ['../src/ui/**/*.mdx', '../src/ui/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [ - '@storybook/addon-links', - '@storybook/addon-essentials', - '@storybook/addon-interactions', - ], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - docs: { - docsPage: true, - }, - webpackFinal: async (config) => { - const custom = await getWebpackConfig(); - - config.plugins.push(new MiniCssExtractPlugin()); - config.resolve.alias = custom.resolve.alias; - - const cssRule = custom.module.rules.find((rule) => rule.test?.test('.css')); - const tsRule = custom.module.rules.find((rule) => rule.test?.test('.tsx')); - tsRule.include = path.resolve('../icons/src'); - - config.module.rules = [ - ...config.module.rules.filter((rule) => !rule.test?.test('.css')), - tsRule, - cssRule, - ]; - - return config; - }, -}; diff --git a/apps/wallet/.storybook/manager.js b/apps/wallet/.storybook/manager.js deleted file mode 100644 index 29be94eff5cfd..0000000000000 --- a/apps/wallet/.storybook/manager.js +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { addons } from '@storybook/addons'; -import { themes } from '@storybook/theming'; - -// Force the theme to light, as our components do not suppor theming -addons.setConfig({ - theme: themes.light, -}); diff --git a/apps/wallet/.storybook/preview.js b/apps/wallet/.storybook/preview.js deleted file mode 100644 index 298c2ba2773e4..0000000000000 --- a/apps/wallet/.storybook/preview.js +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import '../src/ui/styles/global.scss'; -import '@fontsource-variable/inter'; -import '@fontsource-variable/red-hat-mono'; -import 'bootstrap-icons/font/bootstrap-icons.scss'; - -import { MemoryRouter } from 'react-router-dom'; - -export const parameters = { - actions: { argTypesRegex: '^on[A-Z].*' }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, - viewport: { - viewports: { - extension: { - name: 'Chrome Extension', - styles: { - height: '600px', - width: '360px', - }, - type: 'mobile', - }, - }, - defaultViewport: 'extension', - }, -}; - -export const decorators = [ - (Story) => ( - - - - ), -]; diff --git a/apps/wallet/README.md b/apps/wallet/README.md deleted file mode 100644 index f4e3ac00ac65f..0000000000000 --- a/apps/wallet/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Sui Wallet - -A Chrome extension wallet for [Sui](https://sui.io). - -# Set Up - -**Requirements**: 18.0.0 or later. - -Dependencies are managed using [`pnpm`](https://pnpm.io/). You can start by installing dependencies in the root of the Sui repository: - -``` -$ pnpm install -``` - -> All `pnpm` commands below are intended to be run in the root of the Sui repo. - -## Build in watch mode (dev) - -To build the extension and watch for changes run: - -``` -pnpm wallet dev -``` - -This will build the app in the [dist/](./dist/) directory, watch for changes and rebuild it. (Also runs prettier to format the files that changed.) - -## Environment Variables - -You can config default network and RPC endpoints by copying [configs/environment/.env.defaults](configs/environment/.env.defaults) and rename it to `configs/environment/.env`. - -For example, to change the default network from DevNet to Local Network, you can change `API_ENV=devNet` to `API_ENV=local`. - -## Building the wallet - -To build the app, run the following command: - -``` -pnpm wallet build -``` - -The output directory is the same [dist/](./dist/), all build artifacts will go there - -## Install the extension to Chrome - -After building the app, the extension needs to be installed to Chrome. Follow the steps to [load an unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked) and install the app from the [dist/](./dist/) directory. - -## Testing - -``` -pnpm wallet test -``` diff --git a/apps/wallet/ampli.json b/apps/wallet/ampli.json deleted file mode 100644 index 8e549cac5efec..0000000000000 --- a/apps/wallet/ampli.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Zone": "us", - "OrgId": "216883", - "WorkspaceId": "d08bae31-a74f-45c2-985d-2f5dc943b2ea", - "SourceId": "409326bd-fc3f-453e-9275-0bab406831d2", - "Branch": "main", - "Version": "6.0.0", - "VersionId": "77fa44dc-250a-4e7e-8b74-164834834066", - "Runtime": "browser:typescript-ampli-v2", - "Platform": "Browser", - "Language": "TypeScript", - "SDK": "@amplitude/analytics-browser@^1.0", - "Path": "./src/shared/analytics/ampli" -} diff --git a/apps/wallet/configs/environment/.env.defaults b/apps/wallet/configs/environment/.env.defaults deleted file mode 100644 index 3d35e6807203b..0000000000000 --- a/apps/wallet/configs/environment/.env.defaults +++ /dev/null @@ -1,12 +0,0 @@ -# Default values for some env variables. Use .env to add/change variables for the -# current environment. - -API_ENV=mainnet -API_ENDPOINT_LOCAL=http://127.0.0.1:5001/ -API_ENDPOINT_LOCAL_FULLNODE=http://127.0.0.1:9000/ -API_ENDPOINT_LOCAL_FAUCET=http://127.0.0.1:9123/gas -API_ENDPOINT_DEV_NET_FULLNODE=https://wallet-rpc.devnet.sui.io/ -API_ENDPOINT_DEV_NET_FAUCET=https://faucet.devnet.sui.io/gas -API_ENDPOINT_TEST_NET_FULLNODE=https://wallet-rpc.testnet.sui.io/ -API_ENDPOINT_TEST_NET_FAUCET=https://faucet.testnet.sui.io/gas -API_ENDPOINT_MAINNET_FULLNODE=https://wallet-rpc.mainnet.sui.io/ diff --git a/apps/wallet/configs/ts/tsconfig.common.json b/apps/wallet/configs/ts/tsconfig.common.json deleted file mode 100644 index c99759af21310..0000000000000 --- a/apps/wallet/configs/ts/tsconfig.common.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "compilerOptions": { - "target": "es2020", - "module": "esnext", - "lib": ["dom", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noFallthroughCasesInSwitch": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "noEmit": false, - "isolatedModules": true, - "outDir": "../../dist", - "baseUrl": "../../", - "sourceMap": true, - "paths": { - // for internal aliases start them with _ for eslint to use the correct import group - "_src/*": ["./src/*"], - "_shared/*": ["./src/shared/*"], - "_app/*": ["./src/ui/app/*"], - "_assets/*": ["./src/ui/assets/*"], - "_images/*": ["./src/ui/assets/images/*"], - "_redux/*": ["./src/ui/app/redux/*"], - "_store": ["./src/ui/app/redux/store/"], - "_store/*": ["./src/ui/app/redux/store/*"], - "_hooks": ["./src/ui/app/hooks/"], - "_helpers": ["./src/ui/app/helpers/"], - "_pages/*": ["./src/ui/app/pages/*"], - "_components/*": ["./src/ui/app/components/*"], - "_messaging/*": ["./src/shared/messaging/*"], - "_messages": ["./src/shared/messaging/messages/"], - "_messages/*": ["./src/shared/messaging/messages/*"], - "_payloads": ["./src/shared/messaging/messages/payloads/"], - "_payloads/*": ["./src/shared/messaging/messages/payloads/*"], - "_styles/*": ["./src/ui/styles/*"], - "_variables": ["./src/ui/styles/variables"], - "_variables/*": ["./src/ui/styles/variables/*"], - "_values": ["./src/ui/styles/values"], - "_values/*": ["./src/ui/styles/values/*"], - "_utils": ["./src/ui/styles/utils"], - "_utils/*": ["./src/ui/styles/utils/*"] - } - }, - "include": ["../../src", "../../tests"], - "exclude": ["../../build", "../../node_modules"] -} diff --git a/apps/wallet/configs/ts/tsconfig.dev.json b/apps/wallet/configs/ts/tsconfig.dev.json deleted file mode 100644 index c7fa048ccff11..0000000000000 --- a/apps/wallet/configs/ts/tsconfig.dev.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "./tsconfig.common", - "compilerOptions": { - "jsx": "react-jsxdev" - } -} diff --git a/apps/wallet/configs/ts/tsconfig.prod.json b/apps/wallet/configs/ts/tsconfig.prod.json deleted file mode 100644 index 4508bb3289a61..0000000000000 --- a/apps/wallet/configs/ts/tsconfig.prod.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "./tsconfig.common", - "compilerOptions": { - "jsx": "react-jsx" - } -} diff --git a/apps/wallet/configs/ts/tsconfig.webpack.json b/apps/wallet/configs/ts/tsconfig.webpack.json deleted file mode 100644 index d651defa4ef24..0000000000000 --- a/apps/wallet/configs/ts/tsconfig.webpack.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.common", - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "esModuleInterop": true - } -} diff --git a/apps/wallet/configs/webpack/webpack.config.common.ts b/apps/wallet/configs/webpack/webpack.config.common.ts deleted file mode 100644 index cd67e4e037d80..0000000000000 --- a/apps/wallet/configs/webpack/webpack.config.common.ts +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { exec } from 'child_process'; -import { resolve } from 'path'; -import { randomBytes } from '@noble/hashes/utils'; -import SentryWebpackPlugin from '@sentry/webpack-plugin'; -import CopyPlugin from 'copy-webpack-plugin'; -import DotEnv from 'dotenv-webpack'; -import gitRevSync from 'git-rev-sync'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import { DefinePlugin, ProvidePlugin } from 'webpack'; -import type { Configuration } from 'webpack'; - -import packageJson from '../../package.json'; - -function generateDateVersion(patch: number) { - const sha = gitRevSync.short(); - const date = new Date(); - const version = [ - String(date.getUTCFullYear()).slice(2), - String(date.getUTCMonth() + 1), - String(date.getUTCDate()), - patch, - ].join('.'); - - return { - version, - version_name: `${version} (${sha})`, - }; -} - -const WALLET_BETA = process.env.WALLET_BETA === 'true'; -const PATCH_VERISON = Number(process.env.PATCH_VERSION) || 0; - -const PROJECT_ROOT = resolve(__dirname, '..', '..'); -const CONFIGS_ROOT = resolve(PROJECT_ROOT, 'configs'); -const SRC_ROOT = resolve(PROJECT_ROOT, 'src'); -const OUTPUT_ROOT = resolve(PROJECT_ROOT, 'dist'); -const TS_CONFIGS_ROOT = resolve(CONFIGS_ROOT, 'ts'); -const IS_DEV = process.env.NODE_ENV === 'development'; -const IS_PROD = process.env.NODE_ENV === 'production'; -const TS_CONFIG_FILE = resolve(TS_CONFIGS_ROOT, `tsconfig.${IS_DEV ? 'dev' : 'prod'}.json`); -const APP_NAME = WALLET_BETA ? 'Sui Wallet (BETA)' : IS_DEV ? 'Sui Wallet (DEV)' : 'Sui Wallet'; - -function loadTsConfig(tsConfigFilePath: string) { - return new Promise((res, rej) => { - exec( - `${resolve(PROJECT_ROOT, 'node_modules', '.bin', 'tsc')} -p ${tsConfigFilePath} --showConfig`, - (error, stdout, stderr) => { - if (error || stderr) { - rej(error || stderr); - } - res(stdout); - }, - ); - }).then( - (tsContent) => JSON.parse(tsContent), - (e) => { - // eslint-disable-next-line no-console - console.error(e); - throw e; - }, - ); -} - -async function generateAliasFromTs() { - const tsConfigJSON = await loadTsConfig(TS_CONFIG_FILE); - const { - compilerOptions: { paths, baseUrl = './' }, - } = tsConfigJSON; - const alias: Record = {}; - if (paths) { - Object.keys(paths).forEach((anAlias) => { - const aliasPath = paths[anAlias][0]; - const adjAlias = anAlias.replace(/\/\*$/gi, ''); - const adjPath = ( - aliasPath.startsWith('./') || aliasPath.startsWith('../') - ? resolve(TS_CONFIGS_ROOT, baseUrl, aliasPath) - : aliasPath - ).replace(/\/\*$/, ''); - alias[adjAlias] = adjPath; - }); - } - return alias; -} - -const commonConfig: () => Promise = async () => { - const alias = await generateAliasFromTs(); - const walletVersionDetails = generateDateVersion(PATCH_VERISON); - const sentryAuthToken = process.env.SENTRY_AUTH_TOKEN; - return { - context: SRC_ROOT, - entry: { - background: './background', - ui: './ui', - 'content-script': './content-script', - 'dapp-interface': './dapp-interface', - }, - output: { - path: OUTPUT_ROOT, - clean: true, - }, - stats: { - preset: 'summary', - timings: true, - errors: true, - warnings: true, - }, - resolve: { - extensions: ['.ts', '.tsx', '.js'], - // Fix .js imports from @mysten/sui since we are importing it from source - extensionAlias: { - '.js': ['.js', '.ts', '.tsx', '.jsx'], - '.mjs': ['.mjs', '.mts'], - '.cjs': ['.cjs', '.cts'], - }, - alias, - fallback: { - crypto: false, - stream: require.resolve('stream-browserify'), - buffer: require.resolve('buffer/'), - }, - }, - module: { - rules: [ - { - test: /\.(t|j)sx?$/, - loader: 'ts-loader', - options: { - configFile: TS_CONFIG_FILE, - }, - exclude: /node_modules/, - }, - { - test: /\.(s)?css$/i, - use: [ - MiniCssExtractPlugin.loader, - { - loader: 'css-loader', - options: { - modules: { - auto: true, - localIdentName: IS_DEV ? '[name]__[local]__[hash:base64:8]' : '[hash:base64]', - exportLocalsConvention: 'dashes', - }, - }, - }, - 'postcss-loader', - 'sass-loader', - ], - }, - { - test: /\.(png|jpg|jpeg|gif)$/, - type: 'asset/resource', - }, - { - test: /\.svg$/i, - issuer: /\.[jt]sx?$/, - resourceQuery: { not: [/url/] }, - use: ['@svgr/webpack'], - }, - ], - }, - plugins: [ - new MiniCssExtractPlugin(), - new HtmlWebpackPlugin({ - chunks: ['ui'], - filename: 'ui.html', - template: resolve(SRC_ROOT, 'ui', 'index.template.html'), - title: APP_NAME, - }), - new CopyPlugin({ - patterns: [ - { - from: resolve(SRC_ROOT, 'manifest', 'icons', '**', '*'), - }, - { - from: resolve(SRC_ROOT, 'manifest', 'manifest.json'), - to: resolve(OUTPUT_ROOT, '[name][ext]'), - transform: (content) => { - const manifestJson = { - ...JSON.parse(content.toString()), - ...walletVersionDetails, - name: APP_NAME, - description: packageJson.description, - ...(IS_DEV - ? { - key: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2HTQu/66edl64fM/SKDnHJmCz9SIYqM/QK7NM3vD1LTE2UNXzHX5Clj8geuoWAYS6HE/aFcd//qPnAh8TnPgqTS3IX+IbZsY/+kcokxIEWHly3eKEHWB32tQsGdJx6tgDzx8TRkFZEcCCdE4pFqQO68W3I/+8AQPosdd5fsIoF6OGKZ/i29mpGkYJSmMroCN5zYCQqvpjTBIkiTkI9TTjxmBid77pHyG4TsHz0wda4KxHV9ZtzZQXB4vexTku/Isczdtif7pDqFEDCAqEkpiGPyKoIuqrxc75IfpzIGFsIylycBr0fZellSsl2M6FM34R99/vUrGj5iWcjNmhYvZ8QIDAQAB', - } - : undefined), - }; - return JSON.stringify(manifestJson, null, 4); - }, - }, - ], - }), - new DotEnv({ - path: resolve(CONFIGS_ROOT, 'environment', '.env'), - defaults: resolve(CONFIGS_ROOT, 'environment', '.env.defaults'), - expand: true, - }), - new DefinePlugin({ - // This brakes bg service, js-sha3 checks if window is defined, - // but it's not defined in background service. - // TODO: check if this is worth investigating a fix and maybe do a separate build for UI and bg? - // 'typeof window': JSON.stringify(typeof {}), - 'process.env.NODE_DEBUG': false, - 'process.env.WALLET_KEYRING_PASSWORD': JSON.stringify( - // eslint-disable-next-line no-restricted-globals - IS_DEV ? 'DEV_PASS' : Buffer.from(randomBytes(64)).toString('hex'), - ), - 'process.env.WALLET_BETA': WALLET_BETA, - 'process.env.APP_NAME': JSON.stringify(APP_NAME), - }), - new ProvidePlugin({ - Buffer: ['buffer', 'Buffer'], - }), - new SentryWebpackPlugin({ - org: 'mysten-labs', - project: 'wallet', - include: OUTPUT_ROOT, - dryRun: !IS_PROD || !sentryAuthToken, - authToken: sentryAuthToken, - release: walletVersionDetails.version, - silent: true, - }), - ], - }; -}; - -export default commonConfig; diff --git a/apps/wallet/configs/webpack/webpack.config.dev.ts b/apps/wallet/configs/webpack/webpack.config.dev.ts deleted file mode 100644 index c85f26c96d055..0000000000000 --- a/apps/wallet/configs/webpack/webpack.config.dev.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import ESLintPlugin from 'eslint-webpack-plugin'; -import type { Configuration } from 'webpack'; -import { merge } from 'webpack-merge'; - -import configCommon from './webpack.config.common'; - -const configDev: Configuration = { - mode: 'development', - devtool: 'cheap-source-map', - plugins: [new ESLintPlugin({ extensions: ['ts', 'tsx', 'js', 'jsx'] })], - watchOptions: { - aggregateTimeout: 600, - }, - stats: { - loggingDebug: ['sass-loader'], - }, -}; - -async function getConfig() { - return merge(await configCommon(), configDev); -} - -export default getConfig; diff --git a/apps/wallet/configs/webpack/webpack.config.prod.ts b/apps/wallet/configs/webpack/webpack.config.prod.ts deleted file mode 100644 index e0f12e6986424..0000000000000 --- a/apps/wallet/configs/webpack/webpack.config.prod.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Configuration } from 'webpack'; -import { merge } from 'webpack-merge'; - -import configCommon from './webpack.config.common'; - -const configProd: Configuration = { - mode: 'production', - devtool: 'source-map', -}; - -async function getConfig() { - return merge(await configCommon(), configProd); -} - -export default getConfig; diff --git a/apps/wallet/package.json b/apps/wallet/package.json deleted file mode 100644 index 5d675c5c2034a..0000000000000 --- a/apps/wallet/package.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "name": "sui-wallet", - "private": true, - "description": "A wallet for Sui", - "main": "./dist/ui.js", - "scripts": { - "build": "pnpm build:prod", - "build:prod": "cross-env NODE_ENV=\"production\" TS_NODE_PROJECT=\"./configs/ts/tsconfig.webpack.json\" webpack --progress", - "build:dev": "cross-env NODE_ENV=\"development\" TS_NODE_PROJECT=\"./configs/ts/tsconfig.webpack.json\" webpack --progress", - "build:beta": "cross-env WALLET_BETA=true NODE_ENV=\"production\" TS_NODE_PROJECT=\"./configs/ts/tsconfig.webpack.json\" webpack --progress", - "prettier:check": "prettier -c --ignore-unknown .", - "prettier:fix": "prettier -w --ignore-unknown .", - "prettier:fix:watch": "onchange '**' -i -f add -f change -j 5 -- prettier -w --ignore-unknown {{file}}", - "eslint:check": "eslint --max-warnings=0 .", - "eslint:fix": "pnpm run eslint:check --fix", - "lint": "pnpm run eslint:check && pnpm run prettier:check", - "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix", - "dev": "pnpm build:dev --watch", - "test": "vitest run", - "test:watch": "vitest", - "playwright": "cross-env PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=\"1\" playwright", - "pack:zip": "web-ext build --source-dir ./dist --overwrite-dest", - "storybook": "storybook dev -p 6007", - "build-storybook": "storybook build", - "preview-storybook": "pnpm dlx serve ./storybook-static -l 6007", - "ampli": "ampli", - "pull-amplitude": "ampli pull web && node prependLicense.mjs && prettier -w ampli.json src/shared/analytics/ampli/index.ts", - "demoApp:dev": "pnpm vite -c ./tests/demo-app/vite.config.ts ./tests/demo-app/ --port 5181" - }, - "repository": { - "type": "git", - "url": "github.com:MystenLabs/sui.git" - }, - "keywords": [ - "sui", - "wallet", - "coins", - "tokens", - "balance" - ], - "author": "Mysten Labs ", - "license": "Apache-2.0", - "devDependencies": { - "@amplitude/ampli": "^1.31.5", - "@amplitude/analytics-types": "^0.20.0", - "@babel/core": "^7.22.9", - "@babel/preset-env": "^7.22.9", - "@babel/preset-typescript": "^7.22.5", - "@playwright/test": "^1.36.1", - "@sentry/react": "^7.59.2", - "@sentry/webpack-plugin": "^1.20.0", - "@storybook/addon-a11y": "^7.1.0", - "@storybook/addon-essentials": "^7.1.0", - "@storybook/addon-interactions": "^7.1.0", - "@storybook/addon-links": "^7.1.0", - "@storybook/addons": "^7.1.0", - "@storybook/blocks": "^7.1.0", - "@storybook/client-api": "^7.6.17", - "@storybook/react": "^7.1.0", - "@storybook/react-webpack5": "^7.1.0", - "@storybook/theming": "^7.1.0", - "@svgr/webpack": "^7.0.0", - "@types/dotenv-webpack": "^7.0.4", - "@types/git-rev-sync": "^2.0.0", - "@types/node": "^20.14.10", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@types/semver": "^7.5.0", - "@types/throttle-debounce": "^5.0.0", - "@types/uuid": "^9.0.2", - "@types/webextension-polyfill": "^0.10.1", - "@types/webpack": "^5.28.1", - "@types/zxcvbn": "^4.4.1", - "@vitejs/plugin-react": "^4.3.1", - "copy-webpack-plugin": "^11.0.0", - "cross-env": "^7.0.3", - "css-loader": "^6.7.3", - "dotenv-webpack": "^8.0.0", - "eslint": "^8.45.0", - "eslint-webpack-plugin": "^4.0.1", - "git-rev-sync": "^3.0.2", - "happy-dom": "^14.11.0", - "html-webpack-plugin": "^5.5.3", - "mini-css-extract-plugin": "^2.7.6", - "onchange": "^7.1.0", - "postcss": "^8.4.39", - "postcss-loader": "^7.3.3", - "postcss-preset-env": "^9.0.0", - "sass": "^1.63.6", - "sass-loader": "^13.3.2", - "storybook": "^7.1.0", - "tailwindcss": "^3.4.4", - "tailwindcss-animate": "^1.0.7", - "ts-loader": "^9.4.4", - "ts-node": "^10.9.2", - "tsconfig-paths": "^4.2.0", - "typescript": "^5.5.3", - "vite": "^5.3.3", - "vite-tsconfig-paths": "^4.3.2", - "vitest": "^2.0.1", - "web-ext": "^7.6.2", - "webpack": "^5.79.0", - "webpack-cli": "^5.0.1", - "webpack-merge": "^5.8.0" - }, - "dependencies": { - "@amplitude/analytics-browser": "^1.10.3", - "@floating-ui/react": "^0.23.0", - "@fontsource-variable/inter": "^5.0.19", - "@fontsource-variable/red-hat-mono": "^5.0.19", - "@growthbook/growthbook": "^0.25.0", - "@growthbook/growthbook-react": "^0.15.0", - "@headlessui/react": "^1.7.15", - "@ledgerhq/errors": "^6.12.4", - "@ledgerhq/hw-transport": "^6.31.0", - "@ledgerhq/hw-transport-webhid": "^6.27.15", - "@ledgerhq/hw-transport-webusb": "^6.27.13", - "@metamask/browser-passworder": "^4.1.0", - "@mysten/core": "workspace:*", - "@mysten/dapp-kit": "^0.14.44", - "@mysten/deepbook": "^0.8.34", - "@mysten/icons": "workspace:*", - "@mysten/kiosk": "^0.9.34", - "@mysten/ledgerjs-hw-app-sui": "^0.4.1", - "@mysten/sui": "^1.18.0", - "@mysten/wallet-standard": "^0.13.20", - "@noble/hashes": "^1.4.0", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-collapsible": "^1.0.3", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-select": "^1.2.2", - "@radix-ui/react-toggle-group": "^1.0.4", - "@reduxjs/toolkit": "^1.9.5", - "@scure/bip32": "^1.4.0", - "@scure/bip39": "^1.3.0", - "@sentry/browser": "^7.61.0", - "@tanstack/react-query": "^5.50.1", - "@tanstack/react-query-persist-client": "^4.29.25", - "bech32": "^2.0.0", - "bignumber.js": "^9.1.1", - "bootstrap-icons": "^1.10.5", - "buffer": "^6.0.3", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "dexie": "^3.2.4", - "dexie-export-import": "^4.0.7", - "formik": "^2.4.2", - "framer-motion": "^10.12.22", - "idb-keyval": "^6.2.1", - "jose": "^5.6.3", - "mitt": "^3.0.1", - "poseidon-lite": "^0.2.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-error-boundary": "^4.0.10", - "react-hook-form": "^7.52.1", - "react-hot-toast": "^2.4.1", - "react-number-format": "^5.2.2", - "react-redux": "^8.1.1", - "react-router-dom": "^6.24.1", - "react-textarea-autosize": "^8.5.2", - "rxjs": "^7.8.1", - "semver": "^7.5.4", - "stream-browserify": "^3.0.0", - "throttle-debounce": "^5.0.0", - "tweetnacl": "^1.0.3", - "uuid": "^9.0.0", - "webextension-polyfill": "^0.10.0", - "yup": "^1.1.1", - "zod": "^3.23.8", - "zustand": "^4.5.4", - "zxcvbn": "^4.4.2" - } -} diff --git a/apps/wallet/playwright.config.ts b/apps/wallet/playwright.config.ts deleted file mode 100644 index f367b4a76689b..0000000000000 --- a/apps/wallet/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { devices } from '@playwright/test'; -import type { PlaywrightTestConfig } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 30 * 1000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: 'http://localhost:3000', - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - userAgent: 'Playwright', - }, - }, - ], - webServer: [ - { - command: 'pnpm demoApp:dev', - port: 5181, - timeout: 30 * 1000, - reuseExistingServer: !process.env.CI, - }, - { - command: - process.env.E2E_RUN_LOCAL_NET_CMD ?? - 'RUST_LOG="consensus=off" cargo run --bin sui -- start --with-faucet --force-regenesis', - port: 9123, - timeout: 120 * 1000, - /* Set this to true to reuse the server instance on step 'Run Local net' in e2e.yml */ - reuseExistingServer: true, - }, - ], -}; - -export default config; diff --git a/apps/wallet/postcss.config.js b/apps/wallet/postcss.config.js deleted file mode 100644 index 86af57e570186..0000000000000 --- a/apps/wallet/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -const postcssPresetEnv = require('postcss-preset-env'); -const tailwind = require('tailwindcss'); - -module.exports = { - plugins: [postcssPresetEnv(), tailwind], -}; diff --git a/apps/wallet/prependLicense.mjs b/apps/wallet/prependLicense.mjs deleted file mode 100644 index a40ed05622e53..0000000000000 --- a/apps/wallet/prependLicense.mjs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { readFile, writeFile } from 'fs/promises'; - -const LICENSE = '// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n'; - -async function prependLicense(filename) { - const content = await readFile(filename, 'utf8'); - writeFile(filename, LICENSE + content); -} - -prependLicense('src/shared/analytics/ampli/index.ts'); diff --git a/apps/wallet/src/background/Alarms.ts b/apps/wallet/src/background/Alarms.ts deleted file mode 100644 index b2119ff3b1c6a..0000000000000 --- a/apps/wallet/src/background/Alarms.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Browser from 'webextension-polyfill'; - -export const autoLockAlarmName = 'auto-lock-alarm'; -export const cleanUpAlarmName = 'clean-up-storage-alarm'; - -class Alarms { - public async setAutoLockAlarm(minutes: number) { - Browser.alarms.create(autoLockAlarmName, { delayInMinutes: minutes }); - } - - public clearAutoLockAlarm() { - return Browser.alarms.clear(autoLockAlarmName); - } - - public async setCleanUpAlarm() { - await Browser.alarms.create(cleanUpAlarmName, { periodInMinutes: 60 * 6 }); // every 6 hours - } -} - -const alarms = new Alarms(); -export default alarms; diff --git a/apps/wallet/src/background/NetworkEnv.ts b/apps/wallet/src/background/NetworkEnv.ts deleted file mode 100644 index 28440170c9ad9..0000000000000 --- a/apps/wallet/src/background/NetworkEnv.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { DEFAULT_API_ENV } from '_app/ApiProvider'; -import { API_ENV, type NetworkEnvType } from '_src/shared/api-env'; -import { isValidUrl } from '_src/shared/utils'; -import mitt from 'mitt'; -import Browser from 'webextension-polyfill'; - -class NetworkEnv { - #events = mitt<{ changed: NetworkEnvType }>(); - - async getActiveNetwork(): Promise { - const { sui_Env, sui_Env_RPC } = await Browser.storage.local.get({ - sui_Env: DEFAULT_API_ENV, - sui_Env_RPC: null, - }); - const adjCustomUrl = sui_Env === API_ENV.customRPC ? sui_Env_RPC : null; - return { env: sui_Env, customRpcUrl: adjCustomUrl }; - } - - async setActiveNetwork(network: NetworkEnvType) { - const { env, customRpcUrl } = network; - if (env === API_ENV.customRPC && !isValidUrl(customRpcUrl)) { - throw new Error(`Invalid custom RPC url ${customRpcUrl}`); - } - await Browser.storage.local.set({ - sui_Env: env, - sui_Env_RPC: customRpcUrl, - }); - this.#events.emit('changed', network); - } - - on = this.#events.on; - - off = this.#events.off; -} - -const networkEnv = new NetworkEnv(); -export default networkEnv; diff --git a/apps/wallet/src/background/Permissions.ts b/apps/wallet/src/background/Permissions.ts deleted file mode 100644 index a54c3804d1f5e..0000000000000 --- a/apps/wallet/src/background/Permissions.ts +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ALL_PERMISSION_TYPES, isValidPermissionTypes } from '_payloads/permissions'; -import type { Permission, PermissionResponse, PermissionType } from '_payloads/permissions'; -import mitt from 'mitt'; -import { catchError, concatMap, filter, from, mergeWith, share, Subject } from 'rxjs'; -import type { Observable } from 'rxjs'; -import { v4 as uuidV4 } from 'uuid'; -import Browser from 'webextension-polyfill'; - -import type { ContentScriptConnection } from './connections/ContentScriptConnection'; -import Tabs from './Tabs'; -import { Window } from './Window'; - -const PERMISSIONS_STORAGE_KEY = 'permissions'; -const PERMISSION_UI_URL = `${Browser.runtime.getURL('ui.html')}#/dapp/connect/`; -const PERMISSION_UI_URL_REGEX = new RegExp(`${PERMISSION_UI_URL}([0-9a-f-]+$)`, 'i'); - -type PermissionEvents = { - connectedAccountsChanged: { - origin: string; - accounts: string[]; - }; -}; - -class Permissions { - #events = mitt(); - - public static getUiUrl(permissionID: string) { - return `${PERMISSION_UI_URL}${encodeURIComponent(permissionID)}`; - } - - public static isPermissionUiUrl(url: string) { - return PERMISSION_UI_URL_REGEX.test(url); - } - - public static getPermissionIDFromUrl(url: string) { - const match = PERMISSION_UI_URL_REGEX.exec(url); - if (match) { - return match[1]; - } - return null; - } - - private _permissionResponses: Subject = new Subject(); - //NOTE: we need at least one subscription in order for this to handle permission requests - public readonly permissionReply: Observable; - - constructor() { - this.permissionReply = this._permissionResponses.pipe( - mergeWith( - Tabs.onRemoved.pipe( - filter((aTab) => { - return ( - Permissions.isPermissionUiUrl(aTab.url || '') && !aTab.nextUrl?.includes('/locked') - ); - }), - ), - ), - concatMap((data) => - from( - (async () => { - let permissionID: string | null; - const response: Partial = { - allowed: false, - accounts: [], - responseDate: new Date().toISOString(), - }; - if ('url' in data) { - permissionID = Permissions.getPermissionIDFromUrl(data.url || ''); - } else { - permissionID = data.id; - response.allowed = data.allowed; - response.accounts = data.accounts; - response.responseDate = data.responseDate; - } - let aPermissionRequest: Permission | null = null; - if (permissionID) { - aPermissionRequest = await this.getPermissionByID(permissionID); - } - if (aPermissionRequest && this.isPendingPermissionRequest(aPermissionRequest)) { - const finalPermission: Permission = { - ...aPermissionRequest, - ...response, - }; - return finalPermission; - } - // ignore the event - return null; - })(), - ).pipe( - filter((data) => data !== null), - concatMap((permission) => - from( - (async () => { - if (permission) { - await this.storePermission(permission); - this.#events.emit('connectedAccountsChanged', { - origin: permission.origin, - accounts: permission.allowed ? permission.accounts : [], - }); - return permission; - } - return null; - })(), - ), - ), - ), - ), - // we ignore any errors and continue to handle other requests - // TODO: expose those errors to dapp? - catchError((_error, originalSource) => originalSource), - share(), - ); - } - - public async startRequestPermissions( - permissionTypes: readonly PermissionType[], - connection: ContentScriptConnection, - requestMsgID: string, - ): Promise { - if (!isValidPermissionTypes(permissionTypes)) { - throw new Error( - `Invalid permission types. Allowed type are ${ALL_PERMISSION_TYPES.join(', ')}`, - ); - } - const { origin } = connection; - const existingPermission = await this.getPermission(origin); - const hasPendingRequest = await this.hasPendingPermissionRequest(origin, existingPermission); - if (hasPendingRequest) { - if (existingPermission) { - const uiUrl = Permissions.getUiUrl(existingPermission.id); - const found = await Tabs.highlight({ url: uiUrl }); - if (!found) { - await new Window(uiUrl).show(); - } - } - throw new Error('Another permission request is pending.'); - } - const alreadyAllowed = await this.hasPermissions(origin, permissionTypes, existingPermission); - if (alreadyAllowed && existingPermission) { - return existingPermission; - } - const pRequest = await this.createPermissionRequest( - connection.origin, - permissionTypes, - connection.originFavIcon, - requestMsgID, - connection.pagelink, - existingPermission, - ); - await new Window(Permissions.getUiUrl(pRequest.id)).show(); - return null; - } - - public handlePermissionResponse(response: PermissionResponse) { - this._permissionResponses.next(response); - } - - public async getPermissions(): Promise> { - return (await Browser.storage.local.get({ [PERMISSIONS_STORAGE_KEY]: {} }))[ - PERMISSIONS_STORAGE_KEY - ]; - } - - public async getPermission( - origin: string, - permission?: Permission | null, - ): Promise { - if (permission && permission.origin !== origin) { - throw new Error( - `Provided permission has different origin from the one provided. "${permission.origin} !== ${origin}"`, - ); - } - if (permission) { - return permission; - } - const permissions = await this.getPermissions(); - return permissions[origin] || null; - } - - public async hasPendingPermissionRequest( - origin: string, - permission?: Permission | null, - ): Promise { - const existingPermission = await this.getPermission(origin, permission); - return !!existingPermission && this.isPendingPermissionRequest(existingPermission); - } - - public async hasPermissions( - origin: string, - permissionTypes: readonly PermissionType[], - permission?: Permission | null, - address?: string, - ): Promise { - const existingPermission = await this.getPermission(origin, permission); - return Boolean( - existingPermission && - existingPermission.allowed && - permissionTypes.every((permissionType) => - existingPermission.permissions.includes(permissionType), - ) && - (!address || (address && existingPermission.accounts.includes(address))), - ); - } - - public async delete(origin: string, specificAccounts: string[] = []) { - const allPermissions = await this.getPermissions(); - const thePermission = allPermissions[origin]; - if (thePermission) { - const remainingAccounts = specificAccounts.length - ? thePermission.accounts.filter((anAccount) => !specificAccounts.includes(anAccount)) - : []; - if (!remainingAccounts.length) { - delete allPermissions[origin]; - } else { - thePermission.accounts = remainingAccounts; - } - await Browser.storage.local.set({ - [PERMISSIONS_STORAGE_KEY]: allPermissions, - }); - this.#events.emit('connectedAccountsChanged', { - origin, - accounts: remainingAccounts, - }); - } - } - - public async ensurePermissionAccountsUpdated(accounts: { address: string }[]) { - const allPermissions = await this.getPermissions(); - const availableAccountsIndex = accounts.reduce>((acc, { address }) => { - acc[address] = true; - return acc; - }, {}); - Object.entries(allPermissions).forEach(async ([origin, { accounts, allowed }]) => { - if (allowed) { - const accountsToDisconnect = accounts.filter( - (anAddress) => !availableAccountsIndex[anAddress], - ); - if (accountsToDisconnect.length) { - await this.delete(origin, accountsToDisconnect); - } - } - }); - } - - public on = this.#events.on; - - public off = this.#events.off; - - private async createPermissionRequest( - origin: string, - permissionTypes: readonly PermissionType[], - favIcon: string | undefined, - requestMsgID: string, - pagelink?: string | undefined, - existingPermission?: Permission | null, - ): Promise { - let permissionToStore: Permission; - if (existingPermission) { - existingPermission.responseDate = null; - existingPermission.requestMsgID = requestMsgID; - if (existingPermission.allowed) { - permissionTypes.forEach((aPermission) => { - if (!existingPermission.permissions.includes(aPermission)) { - existingPermission.permissions.push(aPermission); - } - }); - } else { - existingPermission.permissions = permissionTypes as PermissionType[]; - } - existingPermission.allowed = null; - permissionToStore = existingPermission; - } else { - permissionToStore = { - id: uuidV4(), - accounts: [], - allowed: null, - createdDate: new Date().toISOString(), - origin, - favIcon, - pagelink, - permissions: permissionTypes as PermissionType[], - responseDate: null, - requestMsgID, - }; - } - await this.storePermission(permissionToStore); - return permissionToStore; - } - - private async storePermission(permission: Permission) { - const permissions = await this.getPermissions(); - permissions[permission.origin] = permission; - await Browser.storage.local.set({ - [PERMISSIONS_STORAGE_KEY]: permissions, - }); - } - - private async getPermissionByID(id: string) { - const permissions = await this.getPermissions(); - for (const aPermission of Object.values(permissions)) { - if (aPermission.id === id) { - return aPermission; - } - } - return null; - } - - private isPendingPermissionRequest(permissionRequest: Permission) { - return permissionRequest.responseDate === null; - } -} - -const permissions = new Permissions(); -export default permissions; diff --git a/apps/wallet/src/background/Tabs.ts b/apps/wallet/src/background/Tabs.ts deleted file mode 100644 index 4b0e775326cf0..0000000000000 --- a/apps/wallet/src/background/Tabs.ts +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - BehaviorSubject, - distinctUntilChanged, - filter, - from, - fromEventPattern, - map, - merge, - mergeWith, - share, - Subject, - switchMap, -} from 'rxjs'; -import Browser from 'webextension-polyfill'; -import type { Tabs as BrowserTabs } from 'webextension-polyfill'; - -const onRemovedStream = fromEventPattern<[number, BrowserTabs.OnRemovedRemoveInfoType]>( - (handler) => Browser.tabs.onRemoved.addListener(handler), - (handler) => Browser.tabs.onRemoved.removeListener(handler), -).pipe(share()); - -const onCreatedStream = fromEventPattern( - (handler) => Browser.tabs.onCreated.addListener(handler), - (handler) => Browser.tabs.onCreated.removeListener(handler), -).pipe(share()); - -const onUpdatedStream = fromEventPattern< - [number, BrowserTabs.OnUpdatedChangeInfoType, BrowserTabs.Tab] ->( - (handler) => Browser.tabs.onUpdated.addListener(handler), - (handler) => Browser.tabs.onUpdated.removeListener(handler), -).pipe(share()); - -const onTabActivated = fromEventPattern( - (handler) => Browser.tabs.onActivated.addListener(handler), - (handler) => Browser.tabs.onActivated.removeListener(handler), -).pipe(share()); - -const onWindowFocusChanged = fromEventPattern( - (handler) => Browser.windows.onFocusChanged.addListener(handler), - (handler) => Browser.windows.onFocusChanged.removeListener(handler), -).pipe(share()); - -type TabInfo = { - id: number; - url: string | null; - nextUrl?: string; - closed?: boolean; -}; - -type ActiveOriginInfo = { - origin: string | null; - favIcon: string | null; -}; - -class Tabs { - private tabs: Map = new Map(); - private _onRemoved: Subject = new Subject(); - private _onActiveOrigin: BehaviorSubject = - new BehaviorSubject({ origin: null, favIcon: null }); - - constructor() { - Browser.tabs.query({}).then((tabs) => { - for (const { id, url } of tabs) { - if (id && url) { - this.tabs.set(id, { id, url }); - } - } - }); - onCreatedStream - .pipe(mergeWith(onUpdatedStream.pipe(map(([_1, _2, aTab]) => aTab)))) - .subscribe((aTab) => { - const { id, url } = aTab; - if (id && url) { - const currentTab = this.tabs.get(id); - if (currentTab && currentTab.url && currentTab.url !== url) { - // notify as removed tab when we change the url - this._onRemoved.next({ - id, - url: currentTab.url, - nextUrl: url, - closed: false, - }); - } - this.tabs.set(id, { id, url }); - } - }); - onRemovedStream.subscribe(([tabID]) => { - const tabInfo: TabInfo = this.tabs.get(tabID) || { - id: tabID, - url: null, - }; - tabInfo.closed = true; - this.tabs.delete(tabID); - this._onRemoved.next(tabInfo); - }); - merge( - onWindowFocusChanged.pipe( - switchMap((windowId) => Browser.tabs.query({ active: true, windowId })), - map((tabs) => tabs[0]), - ), - from(Browser.tabs.query({ active: true, lastFocusedWindow: true })).pipe( - map((tabs) => tabs[0]), - ), - onTabActivated.pipe( - switchMap((info) => - merge( - Browser.tabs.get(info.tabId), - onUpdatedStream.pipe( - filter(([tabID]) => info.tabId === tabID), - map(([_1, _2, tab]) => tab), - ), - ), - ), - ), - ) - .pipe( - map((tab) => ({ - origin: tab.url ? new URL(tab.url).origin : null, - favIcon: tab.favIconUrl || null, - })), - distinctUntilChanged( - (prev, current) => prev.origin === current.origin && prev.favIcon === current.favIcon, - ), - ) - .subscribe((activeOrigin) => { - this._onActiveOrigin.next(activeOrigin); - }); - } - - /** - * An observable that emits when a tab wea closed or when the url has changed - */ - public get onRemoved() { - return this._onRemoved.asObservable(); - } - - public get activeOrigin() { - return this._onActiveOrigin.asObservable(); - } - - public async highlight( - option: { windowID?: number } & ( - | { - url: string; - match?: (values: { url: string; inAppRedirectUrl?: string }) => boolean; - } - | { tabID: number } - ), - ) { - let tabToHighlight: BrowserTabs.Tab | null = null; - if ('tabID' in option) { - try { - tabToHighlight = await Browser.tabs.get(option.tabID); - } catch (e) { - //Do nothing - } - } else { - const inAppUrlToMatch = option.url.split('#')[1] || ''; - const tabs = ( - await Browser.tabs.query({ - url: option.url.split('#')[0], - windowId: option.windowID, - }) - ).filter((aTab) => { - let inAppRedirectUrl: string | undefined = undefined; - if (aTab.url === option.url) { - return true; - } - if (!aTab.url) { - return false; - } - try { - const tabURL = new URL(aTab.url); - if (tabURL.hash.startsWith('#/locked?url=')) { - inAppRedirectUrl = decodeURIComponent(tabURL.hash.replace('#/locked?url=', '')); - if (inAppRedirectUrl === inAppUrlToMatch) { - return true; - } - } - } catch (e) { - // do nothing - } - if (option.match && option.match({ url: aTab.url, inAppRedirectUrl })) { - return true; - } - return false; - }); - if (tabs.length) { - tabToHighlight = tabs[0]; - } - } - if (!tabToHighlight) { - return false; - } - if (tabToHighlight.windowId) { - await Browser.windows.update(tabToHighlight.windowId, { - drawAttention: true, - focused: true, - }); - } - await Browser.tabs.highlight({ - tabs: tabToHighlight.index, - windowId: tabToHighlight.windowId, - }); - return true; - } -} - -const tabs = new Tabs(); -export default tabs; diff --git a/apps/wallet/src/background/Transactions.ts b/apps/wallet/src/background/Transactions.ts deleted file mode 100644 index 51f9c24aad4fd..0000000000000 --- a/apps/wallet/src/background/Transactions.ts +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - type ApprovalRequest, - type TransactionDataType, -} from '_payloads/transactions/ApprovalRequest'; -import type { SuiSignTransactionSerialized } from '_payloads/transactions/ExecuteTransactionRequest'; -import { type SignMessageRequest } from '_payloads/transactions/SignMessage'; -import type { TransactionRequestResponse } from '_payloads/transactions/ui/TransactionRequestResponse'; -import type { ContentScriptConnection } from '_src/background/connections/ContentScriptConnection'; -import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { type SuiSignMessageOutput } from '@mysten/wallet-standard'; -import { filter, lastValueFrom, map, race, Subject, take } from 'rxjs'; -import { v4 as uuidV4 } from 'uuid'; -import Browser from 'webextension-polyfill'; - -import { Window } from './Window'; - -const STALE_TRANSACTION_MILLISECONDS = 1000 * 60 * 60 * 3; // 3 hours -const TX_STORE_KEY = 'transactions'; - -function openTxWindow(requestID: string) { - return new Window( - Browser.runtime.getURL('ui.html') + `#/dapp/approve/${encodeURIComponent(requestID)}`, - ); -} - -class Transactions { - private _txResponseMessages = new Subject(); - - public async executeOrSignTransaction( - { - tx, - sign, - }: - | { tx: TransactionDataType; sign?: undefined } - | { - tx?: undefined; - sign: SuiSignTransactionSerialized; - }, - connection: ContentScriptConnection, - ): Promise { - const { txResultError, txResult, txSigned } = await this.requestApproval( - tx ?? { - type: 'transaction', - justSign: true, - data: sign.transaction, - account: sign.account, - }, - connection.origin, - connection.originFavIcon, - ); - if (txResultError) { - throw new Error(`Transaction failed with the following error. ${txResultError}`); - } - if (sign && !txSigned) { - throw new Error('Transaction signature is empty'); - } - if (tx) { - if (!txResult || !('digest' in txResult)) { - throw new Error(`Transaction result is empty ${txResult}`); - } - return txResult; - } - return txSigned!; - } - - public async signMessage( - { accountAddress, message }: Required>['args'], - connection: ContentScriptConnection, - ): Promise { - const { txResult, txResultError } = await this.requestApproval( - { type: 'sign-message', accountAddress, message }, - connection.origin, - connection.originFavIcon, - ); - if (txResultError) { - throw new Error(`Signing message failed with the following error ${txResultError}`); - } - if (!txResult) { - throw new Error('Sign message result is empty'); - } - if (!('messageBytes' in txResult)) { - throw new Error('Sign message error, unknown result'); - } - return txResult; - } - - public async getTransactionRequests(): Promise> { - return (await Browser.storage.local.get({ [TX_STORE_KEY]: {} }))[TX_STORE_KEY]; - } - - public async getTransactionRequest(txRequestID: string): Promise { - return (await this.getTransactionRequests())[txRequestID] || null; - } - - public handleMessage(msg: TransactionRequestResponse) { - this._txResponseMessages.next(msg); - } - - public async clearStaleTransactions() { - const now = Date.now(); - const allTransactions = await this.getTransactionRequests(); - let hasChanges = false; - Object.keys(allTransactions).forEach((aTransactionID) => { - const aTransaction = allTransactions[aTransactionID]; - const createdDate = new Date(aTransaction.createdDate); - if ( - aTransaction.approved !== null || - now - createdDate.getTime() >= STALE_TRANSACTION_MILLISECONDS - ) { - delete allTransactions[aTransactionID]; - hasChanges = true; - } - }); - if (hasChanges) { - await this.saveTransactionRequests(allTransactions); - } - } - - private createTransactionRequest( - tx: ApprovalRequest['tx'], - origin: string, - originFavIcon?: string, - ): ApprovalRequest { - return { - id: uuidV4(), - approved: null, - origin, - originFavIcon, - createdDate: new Date().toISOString(), - tx, - }; - } - - private async saveTransactionRequests(txRequests: Record) { - await Browser.storage.local.set({ [TX_STORE_KEY]: txRequests }); - } - - private async storeTransactionRequest(txRequest: ApprovalRequest) { - const txs = await this.getTransactionRequests(); - txs[txRequest.id] = txRequest; - await this.saveTransactionRequests(txs); - } - - private async removeTransactionRequest(txID: string) { - const txs = await this.getTransactionRequests(); - delete txs[txID]; - await this.saveTransactionRequests(txs); - } - - private async requestApproval(request: ApprovalRequest['tx'], origin: string, favIcon?: string) { - const txRequest = this.createTransactionRequest(request, origin, favIcon); - await this.storeTransactionRequest(txRequest); - const popUp = openTxWindow(txRequest.id); - const popUpClose = (await popUp.show()).pipe( - take(1), - map(() => false), - ); - const txResponseMessage = this._txResponseMessages.pipe( - filter((msg) => msg.txID === txRequest.id), - take(1), - ); - return lastValueFrom( - race(popUpClose, txResponseMessage).pipe( - take(1), - map(async (response) => { - await this.removeTransactionRequest(txRequest.id); - if (response) { - const { approved, txResult, txSigned, txResultError } = response; - if (approved) { - txRequest.approved = approved; - txRequest.txResult = txResult; - txRequest.txResultError = txResultError; - txRequest.txSigned = txSigned; - return txRequest; - } - } - throw new Error('Rejected from user'); - }), - ), - ); - } -} - -const transactions = new Transactions(); -export default transactions; diff --git a/apps/wallet/src/background/Window.ts b/apps/wallet/src/background/Window.ts deleted file mode 100644 index d273235fc478f..0000000000000 --- a/apps/wallet/src/background/Window.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { filter, fromEventPattern, share, take, takeWhile } from 'rxjs'; -import Browser from 'webextension-polyfill'; - -const POPUP_WIDTH = 360; -const POPUP_HEIGHT = 680; - -const windowRemovedStream = fromEventPattern( - (handler) => Browser.windows.onRemoved.addListener(handler), - (handler) => Browser.windows.onRemoved.removeListener(handler), -).pipe(share()); - -// This is arbitrary across different operating systems, and unfortunately -// there isn't a great way to tell how much extra height we need to tack on -const windowHeightWithFrame = POPUP_HEIGHT + 28; - -export class Window { - private _id: number | null = null; - private _url: string; - - constructor(url: string) { - this._url = url; - } - - public async show() { - const { width = 0, left = 0, top = 0 } = await Browser.windows.getLastFocused(); - const w = await Browser.windows.create({ - url: this._url, - focused: true, - width: POPUP_WIDTH, - height: windowHeightWithFrame, - type: 'popup', - top: top, - left: Math.floor(left + width - 450), - }); - this._id = typeof w.id === 'undefined' ? null : w.id; - return windowRemovedStream.pipe( - takeWhile(() => this._id !== null), - filter((aWindowID) => aWindowID === this._id), - take(1), - ); - } - - public async close() { - if (this._id !== null) { - await Browser.windows.remove(this._id); - } - } - - /** - * The id of the window. - * {@link Window.show} has to be called first. Otherwise this will be null - * */ - public get id(): number | null { - return this._id; - } -} diff --git a/apps/wallet/src/background/account-sources/AccountSource.ts b/apps/wallet/src/background/account-sources/AccountSource.ts deleted file mode 100644 index bdabbf7919b5f..0000000000000 --- a/apps/wallet/src/background/account-sources/AccountSource.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Serializable } from '_src/shared/cryptography/keystore'; - -import { getDB } from '../db'; -import { - clearEphemeralValue, - getEphemeralValue, - setEphemeralValue, -} from '../session-ephemeral-values'; - -export type AccountSourceType = 'mnemonic' | 'qredo'; - -export abstract class AccountSource< - T extends AccountSourceSerialized = AccountSourceSerialized, - V extends Serializable = Serializable, -> { - readonly id: string; - readonly type: AccountSourceType; - - constructor({ id, type }: { type: AccountSourceType; id: string }) { - this.id = id; - this.type = type; - } - - abstract toUISerialized(): Promise; - abstract isLocked(): Promise; - abstract lock(): Promise; - - protected async getStoredData() { - const data = await (await getDB()).accountSources.get(this.id); - if (!data) { - throw new Error(`Account data not found. (id: ${this.id})`); - } - return data as T; - } - - protected getEphemeralValue(): Promise { - return getEphemeralValue(this.id); - } - - protected setEphemeralValue(value: V) { - return setEphemeralValue(this.id, value); - } - - protected clearEphemeralValue() { - return clearEphemeralValue(this.id); - } -} - -export interface AccountSourceSerialized { - readonly id: string; - readonly type: AccountSourceType; - readonly createdAt: number; -} - -export type AccountSourceSerializedUI = { - readonly id: string; - readonly type: AccountSourceType; - readonly isLocked: boolean; -}; diff --git a/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts b/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts deleted file mode 100644 index 4a6f712b14450..0000000000000 --- a/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - entropyToMnemonic, - entropyToSerialized, - getRandomEntropy, - toEntropy, - validateEntropy, -} from '_shared/utils/bip39'; -import { decrypt, encrypt } from '_src/shared/cryptography/keystore'; -import { mnemonicToSeedHex } from '@mysten/sui/cryptography'; -import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; -import { sha256 } from '@noble/hashes/sha256'; -import { bytesToHex } from '@noble/hashes/utils'; -import Dexie from 'dexie'; - -import { getAccountSources } from '.'; -import { getAllAccounts } from '../accounts'; -import { MnemonicAccount, type MnemonicSerializedAccount } from '../accounts/MnemonicAccount'; -import { setupAutoLockAlarm } from '../auto-lock-accounts'; -import { backupDB, getDB } from '../db'; -import { makeUniqueKey } from '../storage-utils'; -import { - AccountSource, - type AccountSourceSerialized, - type AccountSourceSerializedUI, -} from './AccountSource'; -import { accountSourcesEvents } from './events'; - -type DataDecrypted = { - entropyHex: string; - mnemonicSeedHex: string; -}; - -interface MnemonicAccountSourceSerialized extends AccountSourceSerialized { - type: 'mnemonic'; - encryptedData: string; - // hash of entropy to be used for comparing sources (even when locked) - sourceHash: string; -} - -interface MnemonicAccountSourceSerializedUI extends AccountSourceSerializedUI { - type: 'mnemonic'; -} - -export function makeDerivationPath(index: number) { - // currently returns only Ed25519 path - return `m/44'/784'/${index}'/0'/0'`; -} - -export function deriveKeypairFromSeed(mnemonicSeedHex: string, derivationPath: string) { - return Ed25519Keypair.deriveKeypairFromSeed(mnemonicSeedHex, derivationPath); -} - -export class MnemonicAccountSource extends AccountSource< - MnemonicAccountSourceSerialized, - DataDecrypted -> { - static async createNew({ - password, - entropyInput, - }: { - password: string; - entropyInput?: Uint8Array; - }) { - const entropy = entropyInput || getRandomEntropy(); - if (!validateEntropy(entropy)) { - throw new Error("Can't create Mnemonic account source, invalid entropy"); - } - const dataSerialized: MnemonicAccountSourceSerialized = { - id: makeUniqueKey(), - type: 'mnemonic', - encryptedData: await MnemonicAccountSource.createEncryptedData(entropy, password), - sourceHash: bytesToHex(sha256(entropy)), - createdAt: Date.now(), - }; - const allAccountSources = await getAccountSources(); - for (const anAccountSource of allAccountSources) { - if ( - anAccountSource instanceof MnemonicAccountSource && - (await anAccountSource.sourceHash) === dataSerialized.sourceHash - ) { - throw new Error('Mnemonic account source already exists'); - } - } - return dataSerialized; - } - - static isOfType( - serialized: AccountSourceSerialized, - ): serialized is MnemonicAccountSourceSerialized { - return serialized.type === 'mnemonic'; - } - - static async save( - serialized: MnemonicAccountSourceSerialized, - { - skipBackup = false, - skipEventEmit = false, - }: { skipBackup?: boolean; skipEventEmit?: boolean } = {}, - ) { - await (await Dexie.waitFor(getDB())).accountSources.put(serialized); - if (!skipBackup) { - await backupDB(); - } - if (!skipEventEmit) { - accountSourcesEvents.emit('accountSourcesChanged'); - } - return new MnemonicAccountSource(serialized.id); - } - - static createEncryptedData(entropy: Uint8Array, password: string) { - const decryptedData: DataDecrypted = { - entropyHex: entropyToSerialized(entropy), - mnemonicSeedHex: mnemonicToSeedHex(entropyToMnemonic(entropy)), - }; - return encrypt(password, decryptedData); - } - - constructor(id: string) { - super({ type: 'mnemonic', id }); - } - - async isLocked() { - return (await this.getEphemeralValue()) === null; - } - - async unlock(password: string) { - await this.setEphemeralValue(await this.#decryptStoredData(password)); - await setupAutoLockAlarm(); - accountSourcesEvents.emit('accountSourceStatusUpdated', { accountSourceID: this.id }); - } - - async verifyPassword(password: string) { - const { encryptedData } = await this.getStoredData(); - await decrypt(password, encryptedData); - } - - async lock() { - await this.clearEphemeralValue(); - accountSourcesEvents.emit('accountSourceStatusUpdated', { accountSourceID: this.id }); - } - - async deriveAccount({ derivationPathIndex }: { derivationPathIndex?: number } = {}): Promise< - Omit - > { - const derivationPath = - typeof derivationPathIndex !== 'undefined' - ? makeDerivationPath(derivationPathIndex) - : await this.#getAvailableDerivationPath(); - const keyPair = await this.deriveKeyPair(derivationPath); - return MnemonicAccount.createNew({ keyPair, derivationPath, sourceID: this.id }); - } - - async deriveKeyPair(derivationPath: string) { - const data = await this.getEphemeralValue(); - if (!data) { - throw new Error(`Mnemonic account source ${this.id} is locked`); - } - return deriveKeypairFromSeed(data.mnemonicSeedHex, derivationPath); - } - - async toUISerialized(): Promise { - const { type } = await this.getStoredData(); - return { - id: this.id, - type, - isLocked: await this.isLocked(), - }; - } - - async getEntropy(password?: string) { - let data = await this.getEphemeralValue(); - if (password && !data) { - data = await this.#decryptStoredData(password); - } - if (!data) { - throw new Error(`Mnemonic account source ${this.id} is locked`); - } - return data.entropyHex; - } - - get sourceHash() { - return this.getStoredData().then(({ sourceHash }) => sourceHash); - } - - async verifyRecoveryData(entropy: string) { - const newEntropyHash = bytesToHex(sha256(toEntropy(entropy))); - if (newEntropyHash !== (await this.sourceHash)) { - throw new Error("Wrong passphrase, doesn't match the existing one"); - } - return true; - } - - async #getAvailableDerivationPath() { - const derivationPathMap: Record = {}; - for (const anAccount of await getAllAccounts({ sourceID: this.id })) { - if (anAccount instanceof MnemonicAccount && (await anAccount.sourceID) === this.id) { - derivationPathMap[await anAccount.derivationPath] = true; - } - } - let index = 0; - let derivationPath = ''; - let temp; - do { - temp = makeDerivationPath(index++); - if (!derivationPathMap[temp]) { - derivationPath = temp; - } - } while (derivationPath === '' && index < 10000); - if (!derivationPath) { - throw new Error('Failed to find next available derivation path'); - } - return derivationPath; - } - - async #decryptStoredData(password: string) { - const { encryptedData } = await this.getStoredData(); - return decrypt(password, encryptedData); - } -} diff --git a/apps/wallet/src/background/account-sources/QredoAccountSource.ts b/apps/wallet/src/background/account-sources/QredoAccountSource.ts deleted file mode 100644 index bf3a914ed5dc9..0000000000000 --- a/apps/wallet/src/background/account-sources/QredoAccountSource.ts +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { decrypt, encrypt } from '_src/shared/cryptography/keystore'; -import { QredoAPI } from '_src/shared/qredo-api'; -import Dexie from 'dexie'; - -import { getAccountSources } from '.'; -import { setupAutoLockAlarm } from '../auto-lock-accounts'; -import { backupDB, getDB } from '../db'; -import { type QredoConnectIdentity } from '../qredo/types'; -import { isSameQredoConnection } from '../qredo/utils'; -import { makeUniqueKey } from '../storage-utils'; -import { - AccountSource, - type AccountSourceSerialized, - type AccountSourceSerializedUI, -} from './AccountSource'; -import { accountSourcesEvents } from './events'; - -type DataDecrypted = { - refreshToken: string; -}; - -type EphemeralData = { - refreshToken: string; - accessToken: string; -}; - -interface QredoAccountSourceSerialized extends AccountSourceSerialized, QredoConnectIdentity { - type: 'qredo'; - encrypted: string; - originFavIcon: string; -} - -interface QredoAccountSourceSerializedUI extends AccountSourceSerializedUI, QredoConnectIdentity { - type: 'qredo'; - originFavIcon: string; -} - -export class QredoAccountSource extends AccountSource { - constructor(id: string) { - super({ type: 'qredo', id }); - } - static async createNew({ - password, - apiUrl, - organization, - origin, - service, - refreshToken, - originFavIcon, - }: { - password: string; - apiUrl: string; - organization: string; - origin: string; - service: string; - refreshToken: string; - originFavIcon: string; - }) { - const decryptedData: DataDecrypted = { - refreshToken, - }; - const dataSerialized: QredoAccountSourceSerialized = { - id: makeUniqueKey(), - type: 'qredo', - apiUrl, - organization, - origin, - service, - encrypted: await encrypt(password, decryptedData), - originFavIcon, - createdAt: Date.now(), - }; - const allAccountSources = await getAccountSources(); - for (const anAccountSource of allAccountSources) { - if ( - anAccountSource instanceof QredoAccountSource && - isSameQredoConnection( - { - apiUrl: await anAccountSource.apiUrl, - organization: await anAccountSource.organization, - origin: await anAccountSource.origin, - service: await anAccountSource.service, - }, - { id: dataSerialized.id, apiUrl, organization, origin, service }, - ) - ) { - throw new Error('Qredo account source already exists'); - } - } - return dataSerialized; - } - - static isOfType(serialized: AccountSourceSerialized): serialized is QredoAccountSourceSerialized { - return serialized.type === 'qredo'; - } - - static async save( - serialized: QredoAccountSourceSerialized, - { - skipBackup = false, - skipEventEmit = false, - }: { skipBackup?: boolean; skipEventEmit?: boolean } = {}, - ) { - await (await Dexie.waitFor(getDB())).accountSources.put(serialized); - if (!skipBackup) { - await backupDB(); - } - if (!skipEventEmit) { - accountSourcesEvents.emit('accountSourcesChanged'); - } - return new QredoAccountSource(serialized.id); - } - - async toUISerialized(): Promise { - const { apiUrl, id, organization, origin, service, originFavIcon } = await this.getStoredData(); - return { - id, - type: 'qredo', - origin, - apiUrl, - organization, - service, - isLocked: await this.isLocked(), - originFavIcon, - }; - } - - async isLocked(): Promise { - return !(await this.getEphemeralValue()); - } - - async lock(): Promise { - await this.clearEphemeralValue(); - accountSourcesEvents.emit('accountSourceStatusUpdated', { accountSourceID: this.id }); - } - - async unlock(password: string) { - const { encrypted } = await this.getStoredData(); - const { refreshToken } = await decrypt(password, encrypted); - await this.setEphemeralValue({ - refreshToken, - accessToken: await this.#createAccessToken(refreshToken), - }); - await setupAutoLockAlarm(); - accountSourcesEvents.emit('accountSourceStatusUpdated', { accountSourceID: this.id }); - } - - async verifyPassword(password: string) { - const { encrypted } = await this.getStoredData(); - await decrypt(password, encrypted); - } - - async renewAccessToken() { - const ephemeralData = await this.getEphemeralValue(); - if (!ephemeralData) { - throw new Error(`Qredo account source ${this.id} is locked`); - } - const { refreshToken } = ephemeralData; - const accessToken = await this.#createAccessToken(refreshToken); - await this.setEphemeralValue({ refreshToken, accessToken }); - return accessToken; - } - - async #createAccessToken(refreshToken: string): Promise { - const { apiUrl } = await this.getStoredData(); - return ( - await new QredoAPI(this.id, apiUrl).createAccessToken({ - refreshToken, - }) - ).access_token; - } - - get apiUrl() { - return this.getStoredData().then(({ apiUrl }) => apiUrl); - } - - get service() { - return this.getStoredData().then(({ service }) => service); - } - - get organization() { - return this.getStoredData().then(({ organization }) => organization); - } - - get origin() { - return this.getStoredData().then(({ origin }) => origin); - } - - get refreshToken() { - return this.getEphemeralValue().then((data) => { - if (!data) { - throw new Error(`Qredo account source ${this.id} is locked`); - } - return data.refreshToken; - }); - } - - get accessToken() { - return this.getEphemeralValue().then((data) => { - if (!data) { - throw new Error(`Qredo account source ${this.id} is locked`); - } - return data.accessToken; - }); - } -} diff --git a/apps/wallet/src/background/account-sources/events.ts b/apps/wallet/src/background/account-sources/events.ts deleted file mode 100644 index 9a67cf5ad4a30..0000000000000 --- a/apps/wallet/src/background/account-sources/events.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import mitt from 'mitt'; - -type AccountSourcesEvents = { - accountSourcesChanged: void; - accountSourceStatusUpdated: { accountSourceID: string }; -}; - -export const accountSourcesEvents = mitt(); diff --git a/apps/wallet/src/background/account-sources/index.ts b/apps/wallet/src/background/account-sources/index.ts deleted file mode 100644 index 42a6aef83d1cf..0000000000000 --- a/apps/wallet/src/background/account-sources/index.ts +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage, type Message } from '_src/shared/messaging/messages'; -import { - isMethodPayload, - type MethodPayload, -} from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { toEntropy } from '_src/shared/utils/bip39'; - -import { type UiConnection } from '../connections/UiConnection'; -import { getDB } from '../db'; -import { type QredoConnectIdentity } from '../qredo/types'; -import { isSameQredoConnection } from '../qredo/utils'; -import { - type AccountSource, - type AccountSourceSerialized, - type AccountSourceType, -} from './AccountSource'; -import { MnemonicAccountSource } from './MnemonicAccountSource'; -import { QredoAccountSource } from './QredoAccountSource'; - -function toAccountSource(accountSource: AccountSourceSerialized) { - if (MnemonicAccountSource.isOfType(accountSource)) { - return new MnemonicAccountSource(accountSource.id); - } - if (QredoAccountSource.isOfType(accountSource)) { - return new QredoAccountSource(accountSource.id); - } - throw new Error(`Unknown account source of type ${accountSource.type}`); -} - -export async function getAccountSources(filter?: { type: AccountSourceType }) { - const db = await getDB(); - return ( - await (filter?.type - ? await db.accountSources.where('type').equals(filter.type).sortBy('createdAt') - : await db.accountSources.toCollection().sortBy('createdAt')) - ).map(toAccountSource); -} - -export async function getAccountSourceByID(id: string) { - const serializedAccountSource = await (await getDB()).accountSources.get(id); - if (!serializedAccountSource) { - return null; - } - return toAccountSource(serializedAccountSource); -} - -export async function getAllSerializedUIAccountSources() { - return Promise.all( - (await getAccountSources()).map((anAccountSource) => anAccountSource.toUISerialized()), - ); -} - -async function createAccountSource({ - type, - params: { password, entropy }, -}: MethodPayload<'createAccountSource'>['args']) { - switch (type) { - case 'mnemonic': - return ( - await MnemonicAccountSource.save( - await MnemonicAccountSource.createNew({ - password, - entropyInput: entropy ? toEntropy(entropy) : undefined, - }), - ) - ).toUISerialized(); - default: { - throw new Error(`Unknown Account source type ${type}`); - } - } -} - -export async function getQredoAccountSource(filter: string | QredoConnectIdentity) { - let accountSource: AccountSource | null = null; - if (typeof filter === 'string') { - accountSource = await getAccountSourceByID(filter); - } else { - const accountSourceSerialized = ( - await (await getDB()).accountSources.where('type').equals('qredo').toArray() - ) - .filter(QredoAccountSource.isOfType) - .find((anAccountSource) => isSameQredoConnection(filter, anAccountSource)); - accountSource = accountSourceSerialized - ? new QredoAccountSource(accountSourceSerialized.id) - : null; - } - if (!accountSource || !(accountSource instanceof QredoAccountSource)) { - return null; - } - return accountSource; -} - -export async function lockAllAccountSources() { - const allAccountSources = await getAccountSources(); - for (const anAccountSource of allAccountSources) { - await anAccountSource.lock(); - } -} - -export async function accountSourcesHandleUIMessage(msg: Message, uiConnection: UiConnection) { - const { payload } = msg; - if (isMethodPayload(payload, 'createAccountSource')) { - await uiConnection.send( - createMessage>( - { - method: 'accountSourceCreationResponse', - type: 'method-payload', - args: { accountSource: await createAccountSource(payload.args) }, - }, - msg.id, - ), - ); - return true; - } - - if (isMethodPayload(payload, 'unlockAccountSourceOrAccount')) { - const { id, password } = payload.args; - const accountSource = await getAccountSourceByID(id); - if (accountSource) { - if (!password) { - throw new Error('Missing password'); - } - await accountSource.unlock(password); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - if (isMethodPayload(payload, 'lockAccountSourceOrAccount')) { - const accountSource = await getAccountSourceByID(payload.args.id); - if (accountSource) { - await accountSource.lock(); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - if (isMethodPayload(payload, 'getAccountSourceEntropy')) { - const accountSource = await getAccountSourceByID(payload.args.accountSourceID); - if (!accountSource) { - throw new Error('Account source not found'); - } - if (!(accountSource instanceof MnemonicAccountSource)) { - throw new Error('Invalid account source type'); - } - await uiConnection.send( - createMessage>( - { - type: 'method-payload', - method: 'getAccountSourceEntropyResponse', - args: { entropy: await accountSource.getEntropy(payload.args.password) }, - }, - msg.id, - ), - ); - return true; - } - if (isMethodPayload(payload, 'verifyPasswordRecoveryData')) { - const { accountSourceID, entropy } = payload.args.data; - const accountSource = await getAccountSourceByID(accountSourceID); - if (!accountSource) { - throw new Error('Account source not found'); - } - if (!(accountSource instanceof MnemonicAccountSource)) { - throw new Error('Invalid account source type'); - } - await accountSource.verifyRecoveryData(entropy); - uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - return false; -} diff --git a/apps/wallet/src/background/accounts/Account.ts b/apps/wallet/src/background/accounts/Account.ts deleted file mode 100644 index d41aff29e1d2f..0000000000000 --- a/apps/wallet/src/background/accounts/Account.ts +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Serializable } from '_src/shared/cryptography/keystore'; -import { toSerializedSignature, type Keypair } from '@mysten/sui/cryptography'; -import { blake2b } from '@noble/hashes/blake2b'; - -import { setupAutoLockAlarm } from '../auto-lock-accounts'; -import { getDB } from '../db'; -import { - clearEphemeralValue, - getEphemeralValue, - setEphemeralValue, -} from '../session-ephemeral-values'; -import { accountsEvents } from './events'; - -export type AccountType = 'mnemonic-derived' | 'imported' | 'ledger' | 'qredo' | 'zkLogin'; - -export abstract class Account< - T extends SerializedAccount = SerializedAccount, - V extends Serializable | null = Serializable, -> { - readonly id: string; - readonly type: AccountType; - // optimization to avoid accessing storage for properties that don't change - private cachedData: Promise | null = null; - - constructor({ id, type, cachedData }: { id: string; type: AccountType; cachedData?: T }) { - this.id = id; - this.type = type; - if (cachedData) { - this.cachedData = Promise.resolve(cachedData); - } - } - - abstract lock(allowRead: boolean): Promise; - /** - * Indicates if the account is unlocked and allows write actions (eg. signing) - */ - abstract isLocked(): Promise; - abstract toUISerialized(): Promise; - - get address() { - return this.getCachedData().then(({ address }) => address); - } - - get lastUnlockedOn() { - return this.getCachedData().then(({ lastUnlockedOn }) => lastUnlockedOn); - } - - get publicKey() { - return this.getCachedData().then(({ publicKey }) => publicKey); - } - - protected getCachedData() { - if (!this.cachedData) { - this.cachedData = this.getStoredData(); - } - return this.cachedData; - } - - protected async getStoredData() { - const data = await (await getDB()).accounts.get(this.id); - if (!data) { - throw new Error(`Account data not found. (id: ${this.id})`); - } - return data as T; - } - - protected async generateSignature(data: Uint8Array, keyPair: Keypair) { - const digest = blake2b(data, { dkLen: 32 }); - const pubkey = keyPair.getPublicKey(); - const signature = await keyPair.sign(digest); - const signatureScheme = keyPair.getKeyScheme(); - return toSerializedSignature({ - signature, - signatureScheme, - publicKey: pubkey, - }); - } - - protected getEphemeralValue(): Promise { - return getEphemeralValue>(this.id); - } - - protected setEphemeralValue(value: V) { - if (!value) { - return; - } - return setEphemeralValue(this.id, value); - } - - protected clearEphemeralValue() { - return clearEphemeralValue(this.id); - } - - protected async onUnlocked() { - await setupAutoLockAlarm(); - await (await getDB()).accounts.update(this.id, { lastUnlockedOn: Date.now() }); - accountsEvents.emit('accountStatusChanged', { accountID: this.id }); - } - - protected async onLocked(allowRead: boolean) { - // skip clearing last unlocked value to allow read access - // when possible (last unlocked withing time limits) - if (allowRead) { - return; - } - await (await getDB()).accounts.update(this.id, { lastUnlockedOn: null }); - accountsEvents.emit('accountStatusChanged', { accountID: this.id }); - } - - public async setNickname(nickname: string | null) { - await (await getDB()).accounts.update(this.id, { nickname }); - accountsEvents.emit('accountStatusChanged', { accountID: this.id }); - } -} - -export interface SerializedAccount { - readonly id: string; - readonly type: AccountType; - readonly address: string; - readonly publicKey: string | null; - readonly lastUnlockedOn: number | null; - /** - * indicates if it's the selected account in the UI (active account) - */ - readonly selected: boolean; - readonly nickname: string | null; - readonly createdAt: number; -} - -export interface SerializedUIAccount { - readonly id: string; - readonly type: AccountType; - readonly address: string; - /** - * This means the account is not able to sign when isLocked is true (write locked) - */ - readonly isLocked: boolean; - readonly publicKey: string | null; - /** - * Timestamp of the last time the account was unlocked. It is cleared when the account is locked - * because of a user action (manual lock) or lock timer. - * This is used to determine if the account is locked for read or not. (eg. lastUnlockedOn more than 4 hours ago -> read locked) - */ - readonly lastUnlockedOn: number | null; - /** - * indicates if it's the selected account in the UI (active account) - */ - readonly selected: boolean; - readonly nickname: string | null; - readonly isPasswordUnlockable: boolean; - readonly isKeyPairExportable: boolean; -} - -export interface PasswordUnlockableAccount { - readonly unlockType: 'password'; - passwordUnlock(password?: string): Promise; - verifyPassword(password: string): Promise; -} - -export function isPasswordUnLockable(account: unknown): account is PasswordUnlockableAccount { - return !!( - account && - typeof account === 'object' && - 'passwordUnlock' in account && - 'unlockType' in account && - account.unlockType === 'password' - ); -} - -export interface SigningAccount { - readonly canSign: true; - signData(data: Uint8Array): Promise; -} - -export function isSigningAccount(account: any): account is SigningAccount { - return 'signData' in account && 'canSign' in account && account.canSign === true; -} - -export interface KeyPairExportableAccount { - readonly exportableKeyPair: true; - exportKeyPair(password: string): Promise; -} - -export function isKeyPairExportableAccount(account: any): account is KeyPairExportableAccount { - return ( - 'exportKeyPair' in account && - 'exportableKeyPair' in account && - account.exportableKeyPair === true - ); -} diff --git a/apps/wallet/src/background/accounts/ImportedAccount.ts b/apps/wallet/src/background/accounts/ImportedAccount.ts deleted file mode 100644 index 5b98fe0808d43..0000000000000 --- a/apps/wallet/src/background/accounts/ImportedAccount.ts +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { decrypt, encrypt } from '_src/shared/cryptography/keystore'; -import { - fromExportedKeypair, - type LegacyExportedKeyPair, -} from '_src/shared/utils/from-exported-keypair'; - -import { - Account, - type KeyPairExportableAccount, - type PasswordUnlockableAccount, - type SerializedAccount, - type SerializedUIAccount, - type SigningAccount, -} from './Account'; - -type SessionStorageData = { keyPair: LegacyExportedKeyPair | string }; -type EncryptedData = { keyPair: LegacyExportedKeyPair | string }; - -export interface ImportedAccountSerialized extends SerializedAccount { - type: 'imported'; - encrypted: string; - publicKey: string; -} - -export interface ImportedAccountSerializedUI extends SerializedUIAccount { - type: 'imported'; - publicKey: string; -} - -export function isImportedAccountSerializedUI( - account: SerializedUIAccount, -): account is ImportedAccountSerializedUI { - return account.type === 'imported'; -} - -export class ImportedAccount - extends Account - implements PasswordUnlockableAccount, SigningAccount, KeyPairExportableAccount -{ - readonly canSign = true; - readonly unlockType = 'password' as const; - readonly exportableKeyPair = true; - - static async createNew(inputs: { - keyPair: string; - password: string; - }): Promise> { - const keyPair = fromExportedKeypair(inputs.keyPair); - const dataToEncrypt: EncryptedData = { - keyPair: inputs.keyPair, - }; - return { - type: 'imported', - address: keyPair.getPublicKey().toSuiAddress(), - publicKey: keyPair.getPublicKey().toBase64(), - encrypted: await encrypt(inputs.password, dataToEncrypt), - lastUnlockedOn: null, - selected: false, - nickname: null, - createdAt: Date.now(), - }; - } - - static isOfType(serialized: SerializedAccount): serialized is ImportedAccountSerialized { - return serialized.type === 'imported'; - } - - constructor({ id, cachedData }: { id: string; cachedData?: ImportedAccountSerialized }) { - super({ type: 'imported', id, cachedData }); - } - - async lock(allowRead = false): Promise { - await this.clearEphemeralValue(); - await this.onLocked(allowRead); - } - - async isLocked(): Promise { - return !(await this.#getKeyPair()); - } - - async toUISerialized(): Promise { - const { address, publicKey, type, selected, nickname } = await this.getStoredData(); - return { - id: this.id, - type, - address, - publicKey, - isLocked: await this.isLocked(), - lastUnlockedOn: await this.lastUnlockedOn, - selected, - nickname, - isPasswordUnlockable: true, - isKeyPairExportable: true, - }; - } - - async passwordUnlock(password?: string): Promise { - if (!password) { - throw new Error('Missing password to unlock the account'); - } - const { encrypted } = await this.getStoredData(); - const { keyPair } = await decrypt(password, encrypted); - await this.setEphemeralValue({ keyPair }); - await this.onUnlocked(); - } - - async verifyPassword(password: string): Promise { - const { encrypted } = await this.getStoredData(); - await decrypt(password, encrypted); - } - - async signData(data: Uint8Array): Promise { - const keyPair = await this.#getKeyPair(); - if (!keyPair) { - throw new Error(`Account is locked`); - } - return this.generateSignature(data, keyPair); - } - - async exportKeyPair(password: string): Promise { - const { encrypted } = await this.getStoredData(); - const { keyPair } = await decrypt(password, encrypted); - return fromExportedKeypair(keyPair, true).getSecretKey(); - } - - async #getKeyPair() { - const ephemeralData = await this.getEphemeralValue(); - if (ephemeralData) { - return fromExportedKeypair(ephemeralData.keyPair, true); - } - return null; - } -} diff --git a/apps/wallet/src/background/accounts/LedgerAccount.ts b/apps/wallet/src/background/accounts/LedgerAccount.ts deleted file mode 100644 index b9b6bb01998c9..0000000000000 --- a/apps/wallet/src/background/accounts/LedgerAccount.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { decrypt, encrypt } from '_src/shared/cryptography/keystore'; - -import { - Account, - type PasswordUnlockableAccount, - type SerializedAccount, - type SerializedUIAccount, -} from './Account'; - -export interface LedgerAccountSerialized extends SerializedAccount { - type: 'ledger'; - derivationPath: string; - // just used for authentication nothing is stored here at the moment - encrypted: string; -} - -export interface LedgerAccountSerializedUI extends SerializedUIAccount { - type: 'ledger'; - derivationPath: string; -} - -export function isLedgerAccountSerializedUI( - account: SerializedUIAccount, -): account is LedgerAccountSerializedUI { - return account.type === 'ledger'; -} - -type EphemeralData = { - unlocked: true; -}; - -export class LedgerAccount - extends Account - implements PasswordUnlockableAccount -{ - readonly unlockType = 'password'; - - static async createNew({ - address, - publicKey, - password, - derivationPath, - }: { - address: string; - publicKey: string | null; - password: string; - derivationPath: string; - }): Promise> { - return { - type: 'ledger', - address, - publicKey, - encrypted: await encrypt(password, {}), - derivationPath, - lastUnlockedOn: null, - selected: false, - nickname: null, - createdAt: Date.now(), - }; - } - - static isOfType(serialized: SerializedAccount): serialized is LedgerAccountSerialized { - return serialized.type === 'ledger'; - } - - constructor({ id, cachedData }: { id: string; cachedData?: LedgerAccountSerialized }) { - super({ type: 'ledger', id, cachedData }); - } - - async lock(allowRead = false): Promise { - await this.clearEphemeralValue(); - await this.onLocked(allowRead); - } - - async isLocked(): Promise { - return !(await this.getEphemeralValue())?.unlocked; - } - - async passwordUnlock(password?: string): Promise { - if (!password) { - throw new Error('Missing password to unlock the account'); - } - const { encrypted } = await this.getStoredData(); - await decrypt(password, encrypted); - await this.setEphemeralValue({ unlocked: true }); - await this.onUnlocked(); - } - - async verifyPassword(password: string): Promise { - const { encrypted } = await this.getStoredData(); - await decrypt(password, encrypted); - } - - async toUISerialized(): Promise { - const { address, type, publicKey, derivationPath, selected, nickname } = - await this.getStoredData(); - return { - id: this.id, - type, - address, - isLocked: await this.isLocked(), - publicKey, - derivationPath, - lastUnlockedOn: await this.lastUnlockedOn, - selected, - nickname, - isPasswordUnlockable: true, - isKeyPairExportable: false, - }; - } -} diff --git a/apps/wallet/src/background/accounts/MnemonicAccount.ts b/apps/wallet/src/background/accounts/MnemonicAccount.ts deleted file mode 100644 index e949877f07d71..0000000000000 --- a/apps/wallet/src/background/accounts/MnemonicAccount.ts +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { fromExportedKeypair } from '_src/shared/utils/from-exported-keypair'; -import { type Keypair } from '@mysten/sui/cryptography'; - -import { MnemonicAccountSource } from '../account-sources/MnemonicAccountSource'; -import { - Account, - type KeyPairExportableAccount, - type PasswordUnlockableAccount, - type SerializedAccount, - type SerializedUIAccount, - type SigningAccount, -} from './Account'; - -export interface MnemonicSerializedAccount extends SerializedAccount { - type: 'mnemonic-derived'; - sourceID: string; - derivationPath: string; - publicKey: string; -} - -export interface MnemonicSerializedUiAccount extends SerializedUIAccount { - type: 'mnemonic-derived'; - publicKey: string; - derivationPath: string; - sourceID: string; -} - -export function isMnemonicSerializedUiAccount( - account: SerializedUIAccount, -): account is MnemonicSerializedUiAccount { - return account.type === 'mnemonic-derived'; -} - -type SessionStorageData = { keyPair: string }; - -export class MnemonicAccount - extends Account - implements PasswordUnlockableAccount, SigningAccount, KeyPairExportableAccount -{ - readonly unlockType = 'password' as const; - readonly canSign = true; - readonly exportableKeyPair = true; - - static isOfType(serialized: SerializedAccount): serialized is MnemonicSerializedAccount { - return serialized.type === 'mnemonic-derived'; - } - - static createNew({ - keyPair, - derivationPath, - sourceID, - }: { - keyPair: Keypair; - derivationPath: string; - sourceID: string; - }): Omit { - return { - type: 'mnemonic-derived', - sourceID, - address: keyPair.getPublicKey().toSuiAddress(), - derivationPath, - publicKey: keyPair.getPublicKey().toBase64(), - lastUnlockedOn: null, - selected: false, - nickname: null, - createdAt: Date.now(), - }; - } - - constructor({ id, cachedData }: { id: string; cachedData?: MnemonicSerializedAccount }) { - super({ type: 'mnemonic-derived', id, cachedData }); - } - - async isLocked(): Promise { - return !(await this.#getKeyPair()); - } - - async lock(allowRead = false): Promise { - await this.clearEphemeralValue(); - await this.onLocked(allowRead); - } - - async passwordUnlock(password?: string): Promise { - const mnemonicSource = await this.#getMnemonicSource(); - if ((await mnemonicSource.isLocked()) && !password) { - throw new Error('Missing password to unlock the account'); - } - const { derivationPath } = await this.getStoredData(); - if (password) { - await mnemonicSource.unlock(password); - } - await this.setEphemeralValue({ - keyPair: (await mnemonicSource.deriveKeyPair(derivationPath)).getSecretKey(), - }); - await this.onUnlocked(); - } - - async verifyPassword(password: string): Promise { - const mnemonicSource = await this.#getMnemonicSource(); - await mnemonicSource.verifyPassword(password); - } - - async toUISerialized(): Promise { - const { id, type, address, derivationPath, publicKey, sourceID, selected, nickname } = - await this.getStoredData(); - return { - id, - type, - address, - isLocked: await this.isLocked(), - derivationPath, - publicKey, - sourceID, - lastUnlockedOn: await this.lastUnlockedOn, - selected, - nickname, - isPasswordUnlockable: true, - isKeyPairExportable: true, - }; - } - - async signData(data: Uint8Array): Promise { - const keyPair = await this.#getKeyPair(); - if (!keyPair) { - throw new Error(`Account is locked`); - } - return this.generateSignature(data, keyPair); - } - - get derivationPath() { - return this.getCachedData().then(({ derivationPath }) => derivationPath); - } - - get sourceID() { - return this.getCachedData().then(({ sourceID }) => sourceID); - } - - async exportKeyPair(password: string): Promise { - const { derivationPath } = await this.getStoredData(); - const mnemonicSource = await this.#getMnemonicSource(); - await mnemonicSource.unlock(password); - return (await mnemonicSource.deriveKeyPair(derivationPath)).getSecretKey(); - } - - async #getKeyPair() { - const ephemeralData = await this.getEphemeralValue(); - if (ephemeralData) { - return fromExportedKeypair(ephemeralData.keyPair); - } - return null; - } - - async #getMnemonicSource() { - return new MnemonicAccountSource((await this.getStoredData()).sourceID); - } -} diff --git a/apps/wallet/src/background/accounts/QredoAccount.ts b/apps/wallet/src/background/accounts/QredoAccount.ts deleted file mode 100644 index 4095c166436d1..0000000000000 --- a/apps/wallet/src/background/accounts/QredoAccount.ts +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Wallet } from '_src/shared/qredo-api'; - -import { QredoAccountSource } from '../account-sources/QredoAccountSource'; -import { - Account, - type PasswordUnlockableAccount, - type SerializedAccount, - type SerializedUIAccount, -} from './Account'; - -export interface QredoSerializedAccount extends SerializedAccount, Wallet { - type: 'qredo'; - sourceID: string; - publicKey: string; -} - -export interface QredoSerializedUiAccount extends SerializedUIAccount, Wallet { - type: 'qredo'; - publicKey: string; - sourceID: string; -} - -export function isQredoAccountSerializedUI( - account: SerializedUIAccount, -): account is QredoSerializedUiAccount { - return account.type === 'qredo'; -} - -type EphemeralData = { - unlocked: true; -}; - -export class QredoAccount - extends Account - implements PasswordUnlockableAccount -{ - readonly unlockType = 'password' as const; - - static isOfType(serialized: SerializedAccount): serialized is QredoSerializedAccount { - return serialized.type === 'qredo'; - } - - constructor({ id, cachedData }: { id: string; cachedData?: QredoSerializedAccount }) { - super({ type: 'qredo', id, cachedData }); - } - - async isLocked(): Promise { - return (await (await this.#getQredoSource()).isLocked()) || !(await this.getEphemeralValue()); - } - - async lock(allowRead = false): Promise { - await this.clearEphemeralValue(); - await this.onLocked(allowRead); - } - - async passwordUnlock(password?: string): Promise { - if (!password) { - throw new Error('Missing password to unlock the account'); - } - await (await this.#getQredoSource()).unlock(password); - await this.setEphemeralValue({ unlocked: true }); - await this.onUnlocked(); - } - - async verifyPassword(password: string): Promise { - const qredoSource = await this.#getQredoSource(); - await qredoSource.verifyPassword(password); - } - - async toUISerialized(): Promise { - const { - id, - type, - address, - publicKey, - sourceID, - labels, - network, - walletID, - selected, - nickname, - } = await this.getStoredData(); - return { - id, - type, - address, - isLocked: await this.isLocked(), - publicKey, - sourceID, - labels, - network, - walletID, - lastUnlockedOn: await this.lastUnlockedOn, - selected, - nickname, - isPasswordUnlockable: true, - isKeyPairExportable: false, - }; - } - - get sourceID() { - return this.getCachedData().then(({ sourceID }) => sourceID); - } - - get walletID() { - return this.getCachedData().then(({ walletID }) => walletID); - } - - async #getQredoSource() { - return new QredoAccountSource((await this.getStoredData()).sourceID); - } -} diff --git a/apps/wallet/src/background/accounts/events.ts b/apps/wallet/src/background/accounts/events.ts deleted file mode 100644 index 2a6ef66984278..0000000000000 --- a/apps/wallet/src/background/accounts/events.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import mitt from 'mitt'; - -type AccountsEvents = { - accountsChanged: void; - accountStatusChanged: { accountID: string }; - activeAccountChanged: { accountID: string }; -}; - -export const accountsEvents = mitt(); diff --git a/apps/wallet/src/background/accounts/index.ts b/apps/wallet/src/background/accounts/index.ts deleted file mode 100644 index c9aee12a295f0..0000000000000 --- a/apps/wallet/src/background/accounts/index.ts +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage, type Message } from '_src/shared/messaging/messages'; -import { - isMethodPayload, - type MethodPayload, -} from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { type WalletStatusChange } from '_src/shared/messaging/messages/payloads/wallet-status-change'; -import { fromBase64 } from '@mysten/sui/utils'; -import Dexie from 'dexie'; - -import { getAccountSourceByID } from '../account-sources'; -import { accountSourcesEvents } from '../account-sources/events'; -import { MnemonicAccountSource } from '../account-sources/MnemonicAccountSource'; -import { type UiConnection } from '../connections/UiConnection'; -import { backupDB, getDB } from '../db'; -import { LegacyVault } from '../legacy-accounts/LegacyVault'; -import { makeUniqueKey } from '../storage-utils'; -import { - isKeyPairExportableAccount, - isPasswordUnLockable, - isSigningAccount, - type SerializedAccount, -} from './Account'; -import { accountsEvents } from './events'; -import { ImportedAccount } from './ImportedAccount'; -import { LedgerAccount } from './LedgerAccount'; -import { MnemonicAccount } from './MnemonicAccount'; -import { QredoAccount } from './QredoAccount'; -import { ZkLoginAccount, type ZkLoginAccountSerialized } from './zklogin/ZkLoginAccount'; - -function toAccount(account: SerializedAccount) { - if (MnemonicAccount.isOfType(account)) { - return new MnemonicAccount({ id: account.id, cachedData: account }); - } - if (ImportedAccount.isOfType(account)) { - return new ImportedAccount({ id: account.id, cachedData: account }); - } - if (LedgerAccount.isOfType(account)) { - return new LedgerAccount({ id: account.id, cachedData: account }); - } - if (QredoAccount.isOfType(account)) { - return new QredoAccount({ id: account.id, cachedData: account }); - } - if (ZkLoginAccount.isOfType(account)) { - return new ZkLoginAccount({ id: account.id, cachedData: account }); - } - throw new Error(`Unknown account of type ${account.type}`); -} - -export async function getAllAccounts(filter?: { sourceID: string }) { - const db = await getDB(); - let accounts; - if (filter?.sourceID) { - accounts = await db.accounts.where('sourceID').equals(filter.sourceID).sortBy('createdAt'); - } else { - accounts = await db.accounts.toCollection().sortBy('createdAt'); - } - return accounts.map(toAccount); -} - -export async function getAccountByID(id: string) { - const serializedAccount = await (await getDB()).accounts.get(id); - if (!serializedAccount) { - return null; - } - return toAccount(serializedAccount); -} - -export async function getAccountsByAddress(address: string) { - return (await (await getDB()).accounts.where('address').equals(address).toArray()).map(toAccount); -} - -export async function getAllSerializedUIAccounts() { - return Promise.all((await getAllAccounts()).map((anAccount) => anAccount.toUISerialized())); -} - -export async function isAccountsInitialized() { - return (await (await getDB()).accounts.count()) > 0; -} - -export async function getAccountsStatusData( - accountsFilter?: string[], -): Promise['accounts']> { - const allAccounts = await (await getDB()).accounts.toArray(); - return allAccounts - .filter(({ address }) => !accountsFilter || accountsFilter.includes(address)) - .map(({ address, publicKey, nickname }) => ({ address, publicKey, nickname })); -} - -export async function changeActiveAccount(accountID: string) { - const db = await getDB(); - return db.transaction('rw', db.accounts, async () => { - const newSelectedAccount = await db.accounts.get(accountID); - if (!newSelectedAccount) { - throw new Error(`Failed, account with id ${accountID} not found`); - } - await db.accounts.where('id').notEqual(accountID).modify({ selected: false }); - await db.accounts.update(accountID, { selected: true }); - accountsEvents.emit('activeAccountChanged', { accountID }); - }); -} - -async function deleteQredoAccounts(accounts: Omit[]) { - const newAccountsQredoSourceIDs = new Set(); - const walletIDsSet = new Set(); - for (const aNewAccount of accounts) { - if ( - aNewAccount.type === 'qredo' && - 'sourceID' in aNewAccount && - typeof aNewAccount.sourceID === 'string' && - 'walletID' in aNewAccount && - typeof aNewAccount.walletID === 'string' - ) { - newAccountsQredoSourceIDs.add(aNewAccount.sourceID); - walletIDsSet.add(aNewAccount.walletID); - } - } - if (!newAccountsQredoSourceIDs.size) { - return 0; - } - return (await Dexie.waitFor(getDB())).accounts - .where('sourceID') - .anyOf(Array.from(newAccountsQredoSourceIDs.values())) - .filter( - (anExistingAccount) => - anExistingAccount.type === 'qredo' && - 'walletID' in anExistingAccount && - typeof anExistingAccount.walletID === 'string' && - !walletIDsSet.has(anExistingAccount.walletID), - ) - .delete(); -} - -export async function addNewAccounts(accounts: Omit[]) { - const db = await getDB(); - const accountsCreated = await db.transaction('rw', db.accounts, async () => { - // delete all existing qredo accounts that have the same sourceID (come from the same connection) - // and not in the new accounts list - await deleteQredoAccounts(accounts); - const accountInstances = []; - for (const anAccountToAdd of accounts) { - let id = ''; - const existingSameAddressAccounts = await getAccountsByAddress(anAccountToAdd.address); - for (const anExistingAccount of existingSameAddressAccounts) { - if ( - anAccountToAdd.type === 'qredo' && - anExistingAccount instanceof QredoAccount && - 'sourceID' in anAccountToAdd && - anAccountToAdd.sourceID === (await Dexie.waitFor(anExistingAccount.sourceID)) - ) { - id = anExistingAccount.id; - continue; - } - if ( - (await Dexie.waitFor(anExistingAccount.address)) === anAccountToAdd.address && - anExistingAccount.type === anAccountToAdd.type - ) { - // allow importing accounts that have the same address but are of different type - // probably it's an edge case and we used to see this problem with importing - // accounts that were exported from the mnemonic while testing - throw new Error(`Duplicated account ${anAccountToAdd.address}`); - } - } - id = id || makeUniqueKey(); - await db.accounts.put({ ...anAccountToAdd, id }); - const accountInstance = await Dexie.waitFor(getAccountByID(id)); - if (!accountInstance) { - throw new Error(`Something went wrong account with id ${id} not found`); - } - accountInstances.push(accountInstance); - } - const selectedAccount = await db.accounts.filter(({ selected }) => selected).first(); - if (!selectedAccount && accountInstances.length) { - const firstAccount = accountInstances[0]; - await db.accounts.update(firstAccount.id, { selected: true }); - } - return accountInstances; - }); - await backupDB(); - accountsEvents.emit('accountsChanged'); - return accountsCreated; -} - -export async function lockAllAccounts() { - const allAccounts = await getAllAccounts(); - for (const anAccount of allAccounts) { - await anAccount.lock(); - } -} - -export async function accountsHandleUIMessage(msg: Message, uiConnection: UiConnection) { - const { payload } = msg; - if (isMethodPayload(payload, 'lockAccountSourceOrAccount')) { - const account = await getAccountByID(payload.args.id); - if (account) { - await account.lock(); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - if (isMethodPayload(payload, 'setAccountNickname')) { - const { id, nickname } = payload.args; - const account = await getAccountByID(id); - if (account) { - await account.setNickname(nickname); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - if (isMethodPayload(payload, 'unlockAccountSourceOrAccount')) { - const { id, password } = payload.args; - const account = await getAccountByID(id); - if (account) { - if (isPasswordUnLockable(account)) { - await account.passwordUnlock(password); - } else { - await account.unlock(); - } - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - if (isMethodPayload(payload, 'signData')) { - const { id, data } = payload.args; - const account = await getAccountByID(id); - if (!account) { - throw new Error(`Account with address ${id} not found`); - } - if (!isSigningAccount(account)) { - throw new Error(`Account with address ${id} is not a signing account`); - } - await uiConnection.send( - createMessage>( - { - type: 'method-payload', - method: 'signDataResponse', - args: { signature: await account.signData(fromBase64(data)) }, - }, - msg.id, - ), - ); - return true; - } - if (isMethodPayload(payload, 'createAccounts')) { - let newSerializedAccounts: Omit[] = []; - const { type } = payload.args; - if (type === 'mnemonic-derived') { - const { sourceID } = payload.args; - const accountSource = await getAccountSourceByID(payload.args.sourceID); - if (!accountSource) { - throw new Error(`Account source ${sourceID} not found`); - } - if (!(accountSource instanceof MnemonicAccountSource)) { - throw new Error(`Invalid account source type`); - } - newSerializedAccounts.push(await accountSource.deriveAccount()); - } else if (type === 'imported') { - newSerializedAccounts.push(await ImportedAccount.createNew(payload.args)); - } else if (type === 'ledger') { - const { password, accounts } = payload.args; - for (const aLedgerAccount of accounts) { - newSerializedAccounts.push(await LedgerAccount.createNew({ ...aLedgerAccount, password })); - } - } else if (type === 'zkLogin') { - newSerializedAccounts.push(...(await ZkLoginAccount.createNew(payload.args))); - } else { - throw new Error(`Unknown accounts type to create ${type}`); - } - const newAccounts = await addNewAccounts(newSerializedAccounts); - await uiConnection.send( - createMessage>( - { - method: 'accountsCreatedResponse', - type: 'method-payload', - args: { - accounts: await Promise.all( - newAccounts.map(async (aNewAccount) => await aNewAccount.toUISerialized()), - ), - }, - }, - msg.id, - ), - ); - return true; - } - if (isMethodPayload(payload, 'switchAccount')) { - await changeActiveAccount(payload.args.accountID); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - if (isMethodPayload(payload, 'verifyPassword')) { - if (payload.args.legacyAccounts) { - if (!(await LegacyVault.verifyPassword(payload.args.password))) { - throw new Error('Wrong password'); - } - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - const allAccounts = await getAllAccounts(); - for (const anAccount of allAccounts) { - if (isPasswordUnLockable(anAccount)) { - await anAccount.verifyPassword(payload.args.password); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - } - throw new Error('No password protected account found'); - } - if (isMethodPayload(payload, 'storeLedgerAccountsPublicKeys')) { - const { publicKeysToStore } = payload.args; - const db = await getDB(); - // TODO: seems bulkUpdate is supported from v4.0.1-alpha.6 change to it when available - await db.transaction('rw', db.accounts, async () => { - for (const { accountID, publicKey } of publicKeysToStore) { - await db.accounts.update(accountID, { publicKey }); - } - }); - return true; - } - if (isMethodPayload(payload, 'getAccountKeyPair')) { - const { password, accountID } = payload.args; - const account = await getAccountByID(accountID); - if (!account) { - throw new Error(`Account with id ${accountID} not found.`); - } - if (!isKeyPairExportableAccount(account)) { - throw new Error(`Cannot export account with id ${accountID}.`); - } - await uiConnection.send( - createMessage>( - { - type: 'method-payload', - method: 'getAccountKeyPairResponse', - args: { - accountID: account.id, - keyPair: await account.exportKeyPair(password), - }, - }, - msg.id, - ), - ); - return true; - } - if (isMethodPayload(payload, 'removeAccount')) { - const { accountID } = payload.args; - const db = await getDB(); - await db.transaction('rw', db.accounts, db.accountSources, async () => { - const account = await db.accounts.get(accountID); - if (!account) { - throw new Error(`Account with id ${accountID} not found.`); - } - const accountSourceID = - 'sourceID' in account && typeof account.sourceID === 'string' && account.sourceID; - await db.accounts.delete(account.id); - if (accountSourceID) { - const totalSameSourceAccounts = await db.accounts - .where('sourceID') - .equals(accountSourceID) - .count(); - if (totalSameSourceAccounts === 0) { - await db.accountSources.delete(accountSourceID); - } - } - }); - await backupDB(); - accountsEvents.emit('accountsChanged'); - accountSourcesEvents.emit('accountSourcesChanged'); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - if (isMethodPayload(payload, 'acknowledgeZkLoginWarning')) { - const { accountID } = payload.args; - const account = await getAccountByID(accountID); - if (!account) { - throw new Error(`Account with id ${accountID} not found.`); - } - if (!(account instanceof ZkLoginAccount)) { - throw new Error(`Account with id ${accountID} is not a zkLogin account.`); - } - const updates: Partial = { warningAcknowledged: true }; - await (await getDB()).accounts.update(accountID, updates); - accountsEvents.emit('accountStatusChanged', { accountID }); - await uiConnection.send(createMessage({ type: 'done' }, msg.id)); - return true; - } - return false; -} diff --git a/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts b/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts deleted file mode 100644 index cb58534d51aca..0000000000000 --- a/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import networkEnv from '_src/background/NetworkEnv'; -import { API_ENV, type NetworkEnvType } from '_src/shared/api-env'; -import { deobfuscate, obfuscate } from '_src/shared/cryptography/keystore'; -import { getSuiClient } from '_src/shared/sui-client'; -import { fromExportedKeypair } from '_src/shared/utils/from-exported-keypair'; -import { toSerializedSignature, type PublicKey } from '@mysten/sui/cryptography'; -import { normalizeSuiAddress } from '@mysten/sui/utils'; -import { - computeZkLoginAddress, - genAddressSeed, - getZkLoginSignature, - jwtToAddress, - type ComputeZkLoginAddressOptions, -} from '@mysten/sui/zklogin'; -import { blake2b } from '@noble/hashes/blake2b'; -import { decodeJwt } from 'jose'; - -import { addNewAccounts, getAccountsByAddress } from '..'; -import { - Account, - type SerializedAccount, - type SerializedUIAccount, - type SigningAccount, -} from '../Account'; -import { getCurrentEpoch } from './current-epoch'; -import { type ZkLoginProvider } from './providers'; -import { - createPartialZkLoginSignature, - fetchSalt, - prepareZkLogin, - zkLoginAuthenticate, - type PartialZkLoginSignature, -} from './utils'; - -type SerializedNetwork = `${NetworkEnvType['env']}_${NetworkEnvType['customRpcUrl']}`; - -function serializeNetwork(network: NetworkEnvType): SerializedNetwork { - return `${network.env}_${network.customRpcUrl}`; -} - -type CredentialData = { - ephemeralKeyPair: string; - proofs?: PartialZkLoginSignature; - minEpoch: number; - maxEpoch: number; - network: NetworkEnvType; - randomness: string; - jwt: string; -}; - -type SessionStorageData = Partial>; - -type JwtSerializedClaims = { - email: string | null; - fullName: string | null; - firstName: string | null; - lastName: string | null; - picture: string | null; - aud: string; - iss: string; - sub: string; -}; - -export interface ZkLoginAccountSerialized extends SerializedAccount { - type: 'zkLogin'; - provider: ZkLoginProvider; - /** - * the salt used to create the account obfuscated - */ - salt: string; - /** - * obfuscated data that contains user info as it was in jwt - */ - claims: string; - /** - * the addressSeed obfuscated - */ - addressSeed: string; - /** - * the name/key of the claim in claims used for the address sub or email - */ - claimName: 'sub' | 'email'; - warningAcknowledged?: boolean; -} - -export interface ZkLoginAccountSerializedUI extends SerializedUIAccount { - type: 'zkLogin'; - email: string | null; - picture: string | null; - provider: ZkLoginProvider; - warningAcknowledged: boolean; -} - -export function isZkLoginAccountSerializedUI( - account: SerializedUIAccount, -): account is ZkLoginAccountSerializedUI { - return account.type === 'zkLogin'; -} - -async function hasTransactionHistory(address: string): Promise { - const rpc = getSuiClient({ env: API_ENV.mainnet, customRpcUrl: null }); - const [txnIds, fromTxnIds] = await Promise.all([ - rpc.queryTransactionBlocks({ - filter: { - ToAddress: address!, - }, - limit: 1, - }), - rpc.queryTransactionBlocks({ - filter: { - FromAddress: address!, - }, - limit: 1, - }), - ]); - - return !!txnIds.data.length || !!fromTxnIds.data.length; -} - -type CreateNewZkLoginAccountResponseItem = Omit; - -export class ZkLoginAccount - extends Account - implements SigningAccount -{ - readonly canSign = true; - readonly unlockType = 'password' as const; - - static async createNew({ - provider, - }: { - provider: ZkLoginProvider; - }): Promise { - const jwt = await zkLoginAuthenticate({ provider, prompt: true }); - const salt = await fetchSalt(jwt); - const decodedJWT = decodeJwt(jwt); - if (!decodedJWT.sub || !decodedJWT.iss || !decodedJWT.aud) { - throw new Error('Missing jwt data'); - } - if (Array.isArray(decodedJWT.aud)) { - throw new Error('Not supported aud. Aud is an array, string was expected.'); - } - const aud = decodedJWT.aud; - const claims: JwtSerializedClaims = { - email: String(decodedJWT.email || '') || null, - fullName: String(decodedJWT.name || '') || null, - firstName: String(decodedJWT.given_name || '') || null, - lastName: String(decodedJWT.family_name || '') || null, - picture: String(decodedJWT.picture || '') || null, - aud, - iss: decodedJWT.iss, - sub: decodedJWT.sub, - }; - const claimName = 'sub'; - const claimValue = decodedJWT.sub; - - const baseAddressComputationParams: ComputeZkLoginAddressOptions = { - claimName, - claimValue, - iss: decodedJWT.iss, - aud, - userSalt: BigInt(salt), - }; - const legacyAddress = computeZkLoginAddress({ - ...baseAddressComputationParams, - legacyAddress: true, - }); - const nonLegacyAddress = computeZkLoginAddress({ - ...baseAddressComputationParams, - legacyAddress: false, - }); - - const ret: CreateNewZkLoginAccountResponseItem[] = []; - - const accountData: Omit = { - type: 'zkLogin', - claims: await obfuscate(claims), - salt: await obfuscate(salt), - addressSeed: await obfuscate( - genAddressSeed(BigInt(salt), claimName, claimValue, aud).toString(), - ), - provider, - publicKey: null, - lastUnlockedOn: null, - selected: false, - nickname: claims.email || null, - createdAt: Date.now(), - claimName, - }; - - // By default, always import the legacy address. If the legacy and - // non-legacy addresses differ, only import the non-legacy address if it - // has already been used. - ret.push({ - ...accountData, - address: legacyAddress, - }); - if (normalizeSuiAddress(legacyAddress) !== normalizeSuiAddress(nonLegacyAddress)) { - if (await hasTransactionHistory(nonLegacyAddress)) { - ret.push({ - ...accountData, - address: nonLegacyAddress, - nickname: accountData.nickname ? `${accountData.nickname} (address 2)` : null, - }); - } - } - - return ret; - } - - static isOfType(serialized: SerializedAccount): serialized is ZkLoginAccountSerialized { - return serialized.type === 'zkLogin'; - } - - constructor({ id, cachedData }: { id: string; cachedData?: ZkLoginAccountSerialized }) { - super({ type: 'zkLogin', id, cachedData }); - } - - async lock(allowRead = false): Promise { - await this.clearEphemeralValue(); - await this.onLocked(allowRead); - } - - async isLocked(): Promise { - return !(await this.getEphemeralValue()); - } - - async unlock() { - await this.#doLogin(); - } - - async toUISerialized(): Promise { - const { address, publicKey, type, claims, selected, provider, nickname, warningAcknowledged } = - await this.getStoredData(); - const { email, picture } = await deobfuscate(claims); - return { - id: this.id, - type, - address, - publicKey, - isLocked: await this.isLocked(), - lastUnlockedOn: await this.lastUnlockedOn, - email, - picture, - selected, - nickname, - isPasswordUnlockable: false, - provider, - isKeyPairExportable: false, - warningAcknowledged: !!warningAcknowledged, - }; - } - - async signData(data: Uint8Array): Promise { - const digest = blake2b(data, { dkLen: 32 }); - if (await this.isLocked()) { - throw new Error('Account is locked'); - } - const credentials = await this.getEphemeralValue(); - if (!credentials) { - // checking the isLocked above should catch this but keep it just in case - throw new Error('Account is locked'); - } - const activeNetwork = await networkEnv.getActiveNetwork(); - let credentialsData = credentials[serializeNetwork(activeNetwork)]; - const currentEpoch = await getCurrentEpoch(); - // handle cases of different network, current epoch higher than max epoch etc. - if (!this.#areCredentialsValid(currentEpoch, activeNetwork, credentialsData)) { - credentialsData = await this.#doLogin(); - } - const { ephemeralKeyPair, proofs: storedProofs, maxEpoch, jwt, randomness } = credentialsData; - const keyPair = fromExportedKeypair(ephemeralKeyPair); - let proofs = storedProofs; - if (!proofs) { - proofs = await this.#generateProofs( - jwt, - BigInt(randomness), - maxEpoch, - keyPair.getPublicKey(), - activeNetwork, - ); - credentialsData.proofs = proofs; - // store the proofs to avoid creating them again - const newEphemeralValue = await this.getEphemeralValue(); - if (!newEphemeralValue) { - // this should never happen - throw new Error('Missing data, account is locked'); - } - newEphemeralValue[serializeNetwork(activeNetwork)] = credentialsData; - await this.setEphemeralValue(newEphemeralValue); - } - const userSignature = toSerializedSignature({ - signature: await keyPair.sign(digest), - signatureScheme: keyPair.getKeyScheme(), - publicKey: keyPair.getPublicKey(), - }); - const { addressSeed: addressSeedObfuscated } = await this.getStoredData(); - const addressSeed = await deobfuscate(addressSeedObfuscated); - - return getZkLoginSignature({ - inputs: { ...proofs, addressSeed }, - maxEpoch, - userSignature, - }); - } - - #areCredentialsValid( - currentEpoch: number, - activeNetwork: NetworkEnvType, - credentials?: CredentialData, - ): credentials is CredentialData { - if (!credentials) { - return false; - } - const { maxEpoch, network } = credentials; - return ( - activeNetwork.env === network.env && - activeNetwork.customRpcUrl === network.customRpcUrl && - currentEpoch <= maxEpoch - ); - } - - async #doLogin() { - const { provider, claims } = await this.getStoredData(); - const { sub, aud, iss } = await deobfuscate(claims); - const epoch = await getCurrentEpoch(); - const { ephemeralKeyPair, nonce, randomness, maxEpoch } = prepareZkLogin(Number(epoch)); - const jwt = await zkLoginAuthenticate({ provider, nonce, loginHint: sub }); - - const decodedJWT = decodeJwt(jwt); - if (decodedJWT.aud !== aud || decodedJWT.sub !== sub || decodedJWT.iss !== iss) { - throw new Error("Logged in account doesn't match with saved account"); - } - - const activeNetwork = await networkEnv.getActiveNetwork(); - const credentialsData: CredentialData = { - ephemeralKeyPair: ephemeralKeyPair.getSecretKey(), - minEpoch: Number(epoch), - maxEpoch, - network: activeNetwork, - randomness: randomness.toString(), - jwt, - }; - - const ephemeralValue = (await this.getEphemeralValue()) || {}; - ephemeralValue[serializeNetwork(credentialsData.network)] = credentialsData; - await this.setEphemeralValue(ephemeralValue); - - await this.onUnlocked(); - - // On re-auth, we check if the account for the complementary - // legacy/non-legacy address needs to be imported. Additionally, if the - // complementary account has been imported before and is unlocked, we - // update its credentials. This sync does not need to block the login - // process. - this.#syncAlternateAccount(jwt, credentialsData); - - return credentialsData; - } - - async #syncAlternateAccount(jwt: string, credentialsData: CredentialData) { - const salt = await fetchSalt(jwt); - const legacyAddress = jwtToAddress(jwt, salt, true); - const nonLegacyAddress = jwtToAddress(jwt, salt, false); - const decodedJWT = decodeJwt(jwt); - - // if they are the same, do nothing - if (legacyAddress === nonLegacyAddress) { - return; - } - - const { id, ...currentAccount } = await this.getStoredData(); - - const alternateAddress = - currentAccount.address === legacyAddress ? nonLegacyAddress : legacyAddress; - const alternateAccountIsLegacy = alternateAddress === legacyAddress; - const [alternateAccount] = await getAccountsByAddress(alternateAddress); - - // if account exists do nothing - if (alternateAccount) return; - - // If the account is a non-legacy account and has no transaction history, do nothing - if (!alternateAccountIsLegacy && !hasTransactionHistory(alternateAddress)) { - return; - } - - const suffix = alternateAccountIsLegacy ? '' : ' (address 2)'; - - await addNewAccounts([ - { - ...currentAccount, - selected: false, - createdAt: Date.now(), - address: alternateAddress, - nickname: decodedJWT.email ? decodedJWT.email + suffix : currentAccount.nickname + suffix, - lastUnlockedOn: null, - }, - ]); - } - - async #generateProofs( - jwt: string, - randomness: bigint, - maxEpoch: number, - ephemeralPublicKey: PublicKey, - network: NetworkEnvType, - ) { - const { salt: obfuscatedSalt, claimName } = await this.getStoredData(); - const salt = await deobfuscate(obfuscatedSalt); - return await createPartialZkLoginSignature({ - jwt, - ephemeralPublicKey, - userSalt: BigInt(salt), - jwtRandomness: randomness, - keyClaimName: claimName, - maxEpoch, - network, - }); - } -} diff --git a/apps/wallet/src/background/accounts/zklogin/current-epoch.ts b/apps/wallet/src/background/accounts/zklogin/current-epoch.ts deleted file mode 100644 index 3d7bcc0e6490f..0000000000000 --- a/apps/wallet/src/background/accounts/zklogin/current-epoch.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import networkEnv from '_src/background/NetworkEnv'; -import { getFromSessionStorage, setToSessionStorage } from '_src/background/storage-utils'; -import { type NetworkEnvType } from '_src/shared/api-env'; -import { getActiveNetworkSuiClient } from '_src/shared/sui-client'; - -type EpochCacheInfo = { - epoch: number; - epochEndTimestamp: number; -}; - -function epochCacheKey(network: NetworkEnvType) { - return `epoch_cache_${network.env}-${network.customRpcUrl}`; -} - -async function getCurrentEpochRequest(): Promise { - const suiClient = await getActiveNetworkSuiClient(); - const { epoch, epochDurationMs, epochStartTimestampMs } = - await suiClient.getLatestSuiSystemState(); - return { - epoch: Number(epoch), - epochEndTimestamp: Number(epochStartTimestampMs) + Number(epochDurationMs), - }; -} - -export async function getCurrentEpoch() { - const activeNetwork = await networkEnv.getActiveNetwork(); - const cache = await getFromSessionStorage(epochCacheKey(activeNetwork)); - if (cache && Date.now() <= cache.epochEndTimestamp) { - return cache.epoch; - } - const { epoch, epochEndTimestamp } = await getCurrentEpochRequest(); - const newCache: EpochCacheInfo = { - epoch, - epochEndTimestamp: - // add some extra time to existing epochEndTimestamp to avoid making repeating requests while epoch is changing - cache?.epoch === epoch ? cache.epochEndTimestamp + 5 * 1000 : epochEndTimestamp, - }; - await setToSessionStorage(epochCacheKey(activeNetwork), newCache); - return epoch; -} diff --git a/apps/wallet/src/background/accounts/zklogin/providers.ts b/apps/wallet/src/background/accounts/zklogin/providers.ts deleted file mode 100644 index 4cba0256d427e..0000000000000 --- a/apps/wallet/src/background/accounts/zklogin/providers.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Browser from 'webextension-polyfill'; - -export type ZkLoginProvider = 'google' | 'twitch' | 'facebook' | 'kakao'; - -export interface ZkLoginProviderData { - clientID: string; - url: string; - extraParams?: Record; - buildExtraParams?: (inputs: { - prompt?: boolean; - loginHint?: string; - params: URLSearchParams; - }) => void; - enabled: boolean; - hidden?: boolean; - mfaLink?: string; - extractJWT?: (authResponseURL: URL) => Promise; - order: number; -} - -const isDev = process.env.NODE_ENV === 'development'; - -export const zkLoginProviderDataMap: Record = { - google: { - clientID: '946731352276-pk5glcg8cqo38ndb39h7j093fpsphusu.apps.googleusercontent.com', - url: 'https://accounts.google.com/o/oauth2/v2/auth', - extraParams: { - response_type: 'id_token', - scope: 'openid email profile', - }, - buildExtraParams: ({ prompt, loginHint, params }) => { - if (prompt) { - params.append('prompt', 'select_account'); - } - if (loginHint) { - params.append('login_hint', loginHint); - } - }, - enabled: true, - mfaLink: 'https://support.google.com/accounts/answer/185839', - order: 0, - }, - twitch: { - clientID: 'uzpfot3uotf7fp9hklsyctn2735bcw', - url: 'https://id.twitch.tv/oauth2/authorize', - extraParams: { - // adding token in the response_type allows the silent auth to work - without it, every time the auth window is shown - response_type: 'token id_token', - scope: 'openid user:read:email', - claims: JSON.stringify({ - id_token: { - email: null, - email_verified: null, - picture: null, - }, - }), - }, - buildExtraParams: ({ prompt, params }) => { - if (prompt) { - params.append('force_verify', 'true'); - } - }, - enabled: true, - mfaLink: 'https://help.twitch.tv/s/article/two-factor-authentication', - order: 1, - }, - facebook: { - clientID: '829226485248571', - url: 'https://facebook.com/dialog/oauth/', - extraParams: { - response_type: 'id_token', - scope: 'openid email', - }, - enabled: isDev, - hidden: !isDev, - mfaLink: 'https://www.facebook.com/help/148233965247823', - order: 2, - }, - kakao: { - clientID: '5dea1191b184e641d271af1fff43fc44', - url: 'https://kauth.kakao.com/oauth/authorize', - extraParams: { - response_type: 'code', - }, - buildExtraParams: ({ prompt, params }) => { - if (prompt) { - params.append('prompt', 'select_account'); - } - }, - enabled: isDev, - hidden: !isDev, - mfaLink: 'https://cs.kakao.com/helps?service=52&locale=en&category=561', - extractJWT: async (responseURL) => { - const code = responseURL.searchParams.get('code'); - if (!code) { - throw new Error('Code not found'); - } - const res = await fetch('https://kauth.kakao.com/oauth/token', { - method: 'POST', - body: new URLSearchParams({ - grant_type: 'authorization_code', - client_id: zkLoginProviderDataMap.kakao.clientID, - redirect_uri: Browser.identity.getRedirectURL(), - code, - }), - }); - return (await res.json())?.id_token; - }, - order: 3, - }, -}; diff --git a/apps/wallet/src/background/accounts/zklogin/utils.ts b/apps/wallet/src/background/accounts/zklogin/utils.ts deleted file mode 100644 index 6a1e29880fa51..0000000000000 --- a/apps/wallet/src/background/accounts/zklogin/utils.ts +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV, type NetworkEnvType } from '_src/shared/api-env'; -import { fetchWithSentry } from '_src/shared/utils'; -import { type PublicKey } from '@mysten/sui/cryptography'; -import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; -import { - generateNonce, - generateRandomness, - getExtendedEphemeralPublicKey, - type getZkLoginSignature, -} from '@mysten/sui/zklogin'; -import { randomBytes } from '@noble/hashes/utils'; -import { base64url } from 'jose'; -import { v4 as uuidV4 } from 'uuid'; -import Browser from 'webextension-polyfill'; - -import { zkLoginProviderDataMap, type ZkLoginProvider } from './providers'; - -export function prepareZkLogin(currentEpoch: number) { - const maxEpoch = currentEpoch + 2; - const ephemeralKeyPair = new Ed25519Keypair(); - const randomness = generateRandomness(); - const nonce = generateNonce(ephemeralKeyPair.getPublicKey(), maxEpoch, randomness); - return { - ephemeralKeyPair, - randomness, - nonce, - maxEpoch, - }; -} - -const forceSilentGetProviders: ZkLoginProvider[] = ['twitch']; - -/** - * This method does a get request to the authorize url and is used as a workaround - * for `forceSilentGetProviders` that they do the silent login/token refresh using - * html directives or js code to redirect to the redirect_url (instead of response headers) and that forces the launchWebAuthFlow - * to open and close quickly a new window. Which closes the popup window when open but also creates a weird flickering effect. - * - * @param authUrl - */ -async function tryGetRedirectURLSilently(provider: ZkLoginProvider, authUrl: string) { - if (!forceSilentGetProviders.includes(provider)) { - return null; - } - try { - const responseText = await (await fetch(authUrl)).text(); - const redirectURLMatch = - //.exec( - responseText, - ); - if (redirectURLMatch) { - const redirectURL = redirectURLMatch[2]; - if ( - redirectURL.startsWith(`https://${Browser.runtime.id}.chromiumapp.org`) && - redirectURL.includes('id_token=') - ) { - return new URL(redirectURL.replaceAll('&', '&')); - } - } - } catch (e) { - //do nothing - } - return null; -} - -export async function zkLoginAuthenticate({ - provider, - nonce, - loginHint, - prompt, -}: { - provider: ZkLoginProvider; - nonce?: string; - // This can be used for logins after the user has already connected an account - // and we need to make sure that the user logged in with the correct account - // seems only google supports this - loginHint?: string; - prompt?: boolean; -}) { - if (!nonce) { - nonce = base64url.encode(randomBytes(20)); - } - const { clientID, url, extraParams, buildExtraParams, extractJWT } = - zkLoginProviderDataMap[provider]; - const params = new URLSearchParams(extraParams); - params.append('client_id', clientID); - params.append('redirect_uri', Browser.identity.getRedirectURL()); - params.append('nonce', nonce); - if (buildExtraParams) { - buildExtraParams({ prompt, loginHint, params }); - } - const authUrl = `${url}?${params.toString()}`; - let responseURL; - if (!prompt) { - responseURL = await tryGetRedirectURLSilently(provider, authUrl); - } - if (!responseURL) { - responseURL = new URL( - await Browser.identity.launchWebAuthFlow({ - url: authUrl, - interactive: true, - }), - ); - } - let jwt; - if (extractJWT) { - jwt = await extractJWT(responseURL); - } else { - const responseParams = new URLSearchParams(responseURL.hash.replace('#', '')); - jwt = responseParams.get('id_token'); - } - if (!jwt) { - throw new Error('JWT is missing'); - } - return jwt; -} - -const saltRegistryUrl = 'https://salt.api.mystenlabs.com'; - -export async function fetchSalt(jwt: string): Promise { - const response = await fetchWithSentry('fetchUserSalt', `${saltRegistryUrl}/get_salt`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Request-Id': uuidV4(), - }, - body: JSON.stringify({ token: jwt }), - }); - return (await response.json()).salt; -} - -type WalletInputs = { - jwt: string; - ephemeralPublicKey: PublicKey; - maxEpoch: number; - jwtRandomness: bigint; - userSalt: bigint; - keyClaimName?: 'sub' | 'email'; - network: NetworkEnvType; -}; - -export type PartialZkLoginSignature = Omit< - Parameters['0']['inputs'], - 'addressSeed' ->; - -const zkLoginProofsServerUrlDev = 'https://prover-dev.mystenlabs.com/v1'; -const zkLoginProofsServerUrlProd = 'https://prover.mystenlabs.com/v1'; - -export async function createPartialZkLoginSignature({ - jwt, - ephemeralPublicKey, - jwtRandomness, - maxEpoch, - userSalt, - keyClaimName = 'sub', - network, -}: WalletInputs): Promise { - const zkLoginProofsServerUrl = [API_ENV.mainnet, API_ENV.testNet].includes(network.env) - ? zkLoginProofsServerUrlProd - : zkLoginProofsServerUrlDev; - const response = await fetchWithSentry('createZkLoginProofs', zkLoginProofsServerUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Request-Id': uuidV4(), - }, - body: JSON.stringify({ - jwt, - extendedEphemeralPublicKey: getExtendedEphemeralPublicKey(ephemeralPublicKey), - maxEpoch, - jwtRandomness: jwtRandomness.toString(), - salt: userSalt.toString(), - keyClaimName, - }), - }); - return response.json(); -} diff --git a/apps/wallet/src/background/auto-lock-accounts.ts b/apps/wallet/src/background/auto-lock-accounts.ts deleted file mode 100644 index 8e44af92a653a..0000000000000 --- a/apps/wallet/src/background/auto-lock-accounts.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { throttle } from 'throttle-debounce'; - -import Alarms from './Alarms'; -import { getDB, settingsKeys } from './db'; - -export async function getAutoLockMinutes() { - const minutesStored = - (await (await getDB()).settings.get(settingsKeys.autoLockMinutes))?.value || null; - return typeof minutesStored === 'number' ? minutesStored : null; -} - -/** - * minutes as null disables auto-lock - * updates the alarm to the new timeout - */ -export async function setAutoLockMinutes(minutes: number | null) { - await ( - await getDB() - ).settings.put({ - setting: settingsKeys.autoLockMinutes, - value: minutes, - }); - await setupAutoLockAlarm(); -} - -export async function setupAutoLockAlarm() { - const minutes = await getAutoLockMinutes(); - if (!minutes) { - Alarms.clearAutoLockAlarm(); - } else { - Alarms.setAutoLockAlarm(minutes); - } -} - -export const notifyUserActive = throttle( - 5000, - () => { - setupAutoLockAlarm(); - }, - { noTrailing: true }, -); diff --git a/apps/wallet/src/background/connections/Connection.ts b/apps/wallet/src/background/connections/Connection.ts deleted file mode 100644 index f50307187f02f..0000000000000 --- a/apps/wallet/src/background/connections/Connection.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Message } from '_messages'; -import { PortStream } from '_messaging/PortStream'; -import { map, take } from 'rxjs'; -import type { Runtime } from 'webextension-polyfill'; - -export abstract class Connection { - protected _portStream: PortStream; - - constructor(port: Runtime.Port) { - this._portStream = new PortStream(port); - this._portStream.onMessage.subscribe((msg) => this.handleMessage(msg)); - } - - public get onDisconnect() { - return this._portStream.onDisconnect.pipe( - map((port) => ({ port })), - take(1), - ); - } - - public send(msg: Message) { - if (this._portStream.connected) { - return this._portStream.sendMessage(msg); - } - } - - protected abstract handleMessage(msg: Message): void; -} diff --git a/apps/wallet/src/background/connections/ContentScriptConnection.ts b/apps/wallet/src/background/connections/ContentScriptConnection.ts deleted file mode 100644 index 1b72a231cb2d1..0000000000000 --- a/apps/wallet/src/background/connections/ContentScriptConnection.ts +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage } from '_messages'; -import type { Message } from '_messages'; -import type { PortChannelName } from '_messaging/PortChannelName'; -import { isBasePayload, type ErrorPayload } from '_payloads'; -import { isGetAccount } from '_payloads/account/GetAccount'; -import type { GetAccountResponse } from '_payloads/account/GetAccountResponse'; -import type { SetNetworkPayload } from '_payloads/network'; -import { - isAcquirePermissionsRequest, - isHasPermissionRequest, - type AcquirePermissionsResponse, - type HasPermissionsResponse, - type Permission, - type PermissionType, -} from '_payloads/permissions'; -import { - isExecuteTransactionRequest, - isSignTransactionRequest, - type ExecuteTransactionResponse, - type SignTransactionResponse, -} from '_payloads/transactions'; -import Permissions from '_src/background/Permissions'; -import Transactions from '_src/background/Transactions'; -import { FEATURES, growthbook } from '_src/shared/experimentation/features'; -import { isDisconnectApp } from '_src/shared/messaging/messages/payloads/permissions/DisconnectApp'; -import { isQredoConnectPayload } from '_src/shared/messaging/messages/payloads/QredoConnect'; -import { - isSignMessageRequest, - type SignMessageRequest, -} from '_src/shared/messaging/messages/payloads/transactions/SignMessage'; -import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import type { Runtime } from 'webextension-polyfill'; - -import { getAccountsStatusData } from '../accounts'; -import NetworkEnv from '../NetworkEnv'; -import { requestUserApproval } from '../qredo'; -import { Connection } from './Connection'; - -export class ContentScriptConnection extends Connection { - public static readonly CHANNEL: PortChannelName = 'sui_content<->background'; - public readonly origin: string; - public readonly pagelink?: string | undefined; - public readonly originFavIcon: string | undefined; - - constructor(port: Runtime.Port) { - super(port); - this.origin = this.getOrigin(port); - this.pagelink = this.getAppUrl(port); - this.originFavIcon = port.sender?.tab?.favIconUrl; - } - - protected async handleMessage(msg: Message) { - const { payload } = msg; - try { - if (isGetAccount(payload)) { - const { accounts } = await this.ensurePermissions(['viewAccount']); - await this.sendAccounts(accounts, msg.id); - } else if (isHasPermissionRequest(payload)) { - this.send( - createMessage( - { - type: 'has-permissions-response', - result: await Permissions.hasPermissions(this.origin, payload.permissions), - }, - msg.id, - ), - ); - } else if (isAcquirePermissionsRequest(payload)) { - const permission = await Permissions.startRequestPermissions( - payload.permissions, - this, - msg.id, - ); - if (permission) { - this.permissionReply(permission, msg.id); - } - } else if (isExecuteTransactionRequest(payload)) { - if (!payload.transaction.account) { - // make sure we don't execute transactions that doesn't have a specified account - throw new Error('Missing account'); - } - await this.ensurePermissions( - ['viewAccount', 'suggestTransactions'], - payload.transaction.account, - ); - const result = await Transactions.executeOrSignTransaction( - { tx: payload.transaction }, - this, - ); - this.send( - createMessage( - { - type: 'execute-transaction-response', - result: result as SuiTransactionBlockResponse, - }, - msg.id, - ), - ); - } else if (isSignTransactionRequest(payload)) { - if (!payload.transaction.account) { - // make sure we don't execute transactions that doesn't have a specified account - throw new Error('Missing account'); - } - await this.ensurePermissions( - ['viewAccount', 'suggestTransactions'], - payload.transaction.account, - ); - const result = await Transactions.executeOrSignTransaction( - { sign: payload.transaction }, - this, - ); - this.send( - createMessage( - { - type: 'sign-transaction-response', - result: result as SignedTransaction, - }, - msg.id, - ), - ); - } else if (isBasePayload(payload) && payload.type === 'get-network') { - this.send( - createMessage( - { - type: 'set-network', - network: await NetworkEnv.getActiveNetwork(), - }, - msg.id, - ), - ); - } else if (isSignMessageRequest(payload) && payload.args) { - await this.ensurePermissions( - ['viewAccount', 'suggestTransactions'], - payload.args.accountAddress, - ); - const result = await Transactions.signMessage(payload.args, this); - this.send( - createMessage( - { type: 'sign-message-request', return: result }, - msg.id, - ), - ); - } else if (isQredoConnectPayload(payload, 'connect')) { - if (!growthbook.ready) { - await growthbook.loadFeatures(); - } - if (growthbook.isOff(FEATURES.WALLET_QREDO)) { - throw new Error('This feature is not implemented yet.'); - } - await requestUserApproval(payload.args, this, msg); - } else if (isDisconnectApp(payload)) { - await Permissions.delete(this.origin); - } else { - throw new Error(`Unknown message, ${JSON.stringify(msg.payload)}`); - } - } catch (e) { - this.sendError( - { - error: true, - code: -1, - message: (e as Error).message, - }, - msg.id, - ); - } - } - - public permissionReply(permission: Permission, msgID?: string) { - if (permission.origin !== this.origin) { - return; - } - const requestMsgID = msgID || permission.requestMsgID; - if (permission.allowed) { - this.send( - createMessage( - { - type: 'acquire-permissions-response', - result: !!permission.allowed, - }, - requestMsgID, - ), - ); - } else { - this.sendError( - { - error: true, - message: 'Permission rejected', - code: -1, - }, - requestMsgID, - ); - } - } - - private getOrigin(port: Runtime.Port) { - if (port.sender?.origin) { - return port.sender.origin; - } - if (port.sender?.url) { - return new URL(port.sender.url).origin; - } - throw new Error("[ContentScriptConnection] port doesn't include an origin"); - } - - // optional field for the app link. - private getAppUrl(port: Runtime.Port) { - if (port.sender?.url) { - return new URL(port.sender.url).href; - } - return undefined; - } - - private sendError(error: Error, responseForID?: string) { - this.send(createMessage(error, responseForID)); - } - - private async sendAccounts(accounts: string[], responseForID?: string) { - this.send( - createMessage( - { - type: 'get-account-response', - accounts: await getAccountsStatusData(accounts), - }, - responseForID, - ), - ); - } - - private async ensurePermissions(permissions: PermissionType[], account?: string) { - const existingPermission = await Permissions.getPermission(this.origin); - const allowed = await Permissions.hasPermissions( - this.origin, - permissions, - existingPermission, - account, - ); - if (!allowed || !existingPermission) { - throw new Error("Operation not allowed, dapp doesn't have the required permissions"); - } - return existingPermission; - } -} diff --git a/apps/wallet/src/background/connections/UiConnection.ts b/apps/wallet/src/background/connections/UiConnection.ts deleted file mode 100644 index 0c7a4e6877651..0000000000000 --- a/apps/wallet/src/background/connections/UiConnection.ts +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage } from '_messages'; -import type { Message } from '_messages'; -import type { PortChannelName } from '_messaging/PortChannelName'; -import { isBasePayload, type ErrorPayload } from '_payloads'; -import type { LoadedFeaturesPayload } from '_payloads/feature-gating'; -import { isSetNetworkPayload, type SetNetworkPayload } from '_payloads/network'; -import { isGetPermissionRequests, isPermissionResponse } from '_payloads/permissions'; -import type { Permission, PermissionRequests } from '_payloads/permissions'; -import { isDisconnectApp } from '_payloads/permissions/DisconnectApp'; -import type { UpdateActiveOrigin } from '_payloads/tabs/updateActiveOrigin'; -import type { ApprovalRequest } from '_payloads/transactions/ApprovalRequest'; -import { isGetTransactionRequests } from '_payloads/transactions/ui/GetTransactionRequests'; -import type { GetTransactionRequestsResponse } from '_payloads/transactions/ui/GetTransactionRequestsResponse'; -import { isTransactionRequestResponse } from '_payloads/transactions/ui/TransactionRequestResponse'; -import Permissions from '_src/background/Permissions'; -import Tabs from '_src/background/Tabs'; -import Transactions from '_src/background/Transactions'; -import { growthbook } from '_src/shared/experimentation/features'; -import { - isMethodPayload, - type MethodPayload, - type UIAccessibleEntityType, -} from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { - isQredoConnectPayload, - type QredoConnectPayload, -} from '_src/shared/messaging/messages/payloads/QredoConnect'; -import { toEntropy } from '_src/shared/utils/bip39'; -import Dexie from 'dexie'; -import { BehaviorSubject, filter, switchMap, takeUntil } from 'rxjs'; -import Browser from 'webextension-polyfill'; -import type { Runtime } from 'webextension-polyfill'; - -import { - accountSourcesHandleUIMessage, - getAccountSourceByID, - getAllSerializedUIAccountSources, -} from '../account-sources'; -import { accountSourcesEvents } from '../account-sources/events'; -import { MnemonicAccountSource } from '../account-sources/MnemonicAccountSource'; -import { accountsHandleUIMessage, getAllSerializedUIAccounts } from '../accounts'; -import { type AccountType } from '../accounts/Account'; -import { accountsEvents } from '../accounts/events'; -import { getAutoLockMinutes, notifyUserActive, setAutoLockMinutes } from '../auto-lock-accounts'; -import { backupDB, getDB, settingsKeys } from '../db'; -import { clearStatus, doMigration, getStatus } from '../legacy-accounts/storage-migration'; -import NetworkEnv from '../NetworkEnv'; -import { - acceptQredoConnection, - getUIQredoInfo, - getUIQredoPendingRequest, - rejectQredoConnection, -} from '../qredo'; -import { Connection } from './Connection'; - -export class UiConnection extends Connection { - public static readonly CHANNEL: PortChannelName = 'sui_ui<->background'; - private uiAppInitialized: BehaviorSubject = new BehaviorSubject(false); - - constructor(port: Runtime.Port) { - super(port); - this.uiAppInitialized - .pipe( - filter((init) => init), - switchMap(() => Tabs.activeOrigin), - takeUntil(this.onDisconnect), - ) - .subscribe(({ origin, favIcon }) => { - this.send( - createMessage({ - type: 'update-active-origin', - origin, - favIcon, - }), - ); - }); - } - - public async notifyEntitiesUpdated(entitiesType: UIAccessibleEntityType) { - this.send( - createMessage>({ - type: 'method-payload', - method: 'entitiesUpdated', - args: { - type: entitiesType, - }, - }), - ); - } - - protected async handleMessage(msg: Message) { - const { payload, id } = msg; - try { - if (isGetPermissionRequests(payload)) { - this.sendPermissions(Object.values(await Permissions.getPermissions()), id); - // TODO: we should depend on a better message to know if app is initialized - if (!this.uiAppInitialized.value) { - this.uiAppInitialized.next(true); - } - } else if (isPermissionResponse(payload)) { - Permissions.handlePermissionResponse(payload); - } else if (isTransactionRequestResponse(payload)) { - Transactions.handleMessage(payload); - } else if (isGetTransactionRequests(payload)) { - this.sendTransactionRequests( - Object.values(await Transactions.getTransactionRequests()), - id, - ); - } else if (isDisconnectApp(payload)) { - await Permissions.delete(payload.origin, payload.specificAccounts); - this.send(createMessage({ type: 'done' }, id)); - } else if (isBasePayload(payload) && payload.type === 'get-features') { - await growthbook.loadFeatures(); - this.send( - createMessage( - { - type: 'features-response', - features: growthbook.getFeatures(), - attributes: growthbook.getAttributes(), - }, - id, - ), - ); - } else if (isBasePayload(payload) && payload.type === 'get-network') { - this.send( - createMessage( - { - type: 'set-network', - network: await NetworkEnv.getActiveNetwork(), - }, - id, - ), - ); - } else if (isSetNetworkPayload(payload)) { - await NetworkEnv.setActiveNetwork(payload.network); - this.send(createMessage({ type: 'done' }, id)); - } else if (isQredoConnectPayload(payload, 'getPendingRequest')) { - this.send( - createMessage>( - { - type: 'qredo-connect', - method: 'getPendingRequestResponse', - args: { - request: await getUIQredoPendingRequest(payload.args.requestID), - }, - }, - msg.id, - ), - ); - } else if (isQredoConnectPayload(payload, 'getQredoInfo')) { - this.send( - createMessage>( - { - type: 'qredo-connect', - method: 'getQredoInfoResponse', - args: { - qredoInfo: await getUIQredoInfo( - payload.args.qredoID, - payload.args.refreshAccessToken, - ), - }, - }, - msg.id, - ), - ); - } else if (isQredoConnectPayload(payload, 'acceptQredoConnection')) { - this.send( - createMessage>( - { - type: 'qredo-connect', - method: 'acceptQredoConnectionResponse', - args: { accounts: await acceptQredoConnection(payload.args) }, - }, - id, - ), - ); - } else if (isQredoConnectPayload(payload, 'rejectQredoConnection')) { - await rejectQredoConnection(payload.args); - this.send(createMessage({ type: 'done' }, id)); - } else if (isMethodPayload(payload, 'getStoredEntities')) { - const entities = await this.getUISerializedEntities(payload.args.type); - this.send( - createMessage>( - { - method: 'storedEntitiesResponse', - type: 'method-payload', - args: { - type: payload.args.type, - entities, - }, - }, - msg.id, - ), - ); - } else if (await accountSourcesHandleUIMessage(msg, this)) { - return; - } else if (await accountsHandleUIMessage(msg, this)) { - return; - } else if (isMethodPayload(payload, 'getStorageMigrationStatus')) { - this.send( - createMessage>( - { - method: 'storageMigrationStatus', - type: 'method-payload', - args: { - status: await getStatus(), - }, - }, - id, - ), - ); - } else if (isMethodPayload(payload, 'doStorageMigration')) { - await doMigration(payload.args.password); - this.send(createMessage({ type: 'done' }, id)); - } else if (isMethodPayload(payload, 'clearWallet')) { - await Browser.storage.local.clear(); - await Browser.storage.local.set({ - v: -1, - }); - clearStatus(); - const db = await getDB(); - await db.delete(); - await db.open(); - // prevents future run of auto backup process of the db (we removed everything nothing to backup after logout) - await db.settings.put({ setting: settingsKeys.isPopulated, value: true }); - this.send(createMessage({ type: 'done' }, id)); - } else if (isMethodPayload(payload, 'getAutoLockMinutes')) { - await this.send( - createMessage>( - { - type: 'method-payload', - method: 'getAutoLockMinutesResponse', - args: { minutes: await getAutoLockMinutes() }, - }, - msg.id, - ), - ); - } else if (isMethodPayload(payload, 'setAutoLockMinutes')) { - await setAutoLockMinutes(payload.args.minutes); - await this.send(createMessage({ type: 'done' }, msg.id)); - return true; - } else if (isMethodPayload(payload, 'notifyUserActive')) { - await notifyUserActive(); - await this.send(createMessage({ type: 'done' }, msg.id)); - return true; - } else if (isMethodPayload(payload, 'resetPassword')) { - const { password, recoveryData } = payload.args; - if (!recoveryData.length) { - throw new Error('Missing recovery data'); - } - for (const { accountSourceID, entropy } of recoveryData) { - const accountSource = await getAccountSourceByID(accountSourceID); - if (!accountSource) { - throw new Error('Account source not found'); - } - if (!(accountSource instanceof MnemonicAccountSource)) { - throw new Error('Invalid account source type'); - } - await accountSource.verifyRecoveryData(entropy); - } - const db = await getDB(); - const zkLoginType: AccountType = 'zkLogin'; - const accountSourceIDs = recoveryData.map(({ accountSourceID }) => accountSourceID); - await db.transaction('rw', db.accountSources, db.accounts, async () => { - await db.accountSources.where('id').noneOf(accountSourceIDs).delete(); - await db.accounts - .where('type') - .notEqual(zkLoginType) - .filter( - (anAccount) => - !('sourceID' in anAccount) || - typeof anAccount.sourceID !== 'string' || - !accountSourceIDs.includes(anAccount.sourceID), - ) - .delete(); - for (const { accountSourceID, entropy } of recoveryData) { - await db.accountSources.update(accountSourceID, { - encryptedData: await Dexie.waitFor( - MnemonicAccountSource.createEncryptedData(toEntropy(entropy), password), - ), - }); - } - }); - await backupDB(); - accountSourcesEvents.emit('accountSourcesChanged'); - accountsEvents.emit('accountsChanged'); - await this.send(createMessage({ type: 'done' }, msg.id)); - } else { - throw new Error( - `Unhandled message ${msg.id}. (${JSON.stringify( - 'error' in payload ? `${payload.code}-${payload.message}` : payload.type, - )})`, - ); - } - } catch (e) { - this.send( - createMessage( - { - error: true, - code: -1, - message: (e as Error).message, - }, - id, - ), - ); - } - } - - private sendPermissions(permissions: Permission[], requestID: string) { - this.send( - createMessage( - { - type: 'permission-request', - permissions, - }, - requestID, - ), - ); - } - - private sendTransactionRequests(txRequests: ApprovalRequest[], requestID: string) { - this.send( - createMessage( - { - type: 'get-transaction-requests-response', - txRequests, - }, - requestID, - ), - ); - } - - private getUISerializedEntities(type: UIAccessibleEntityType) { - switch (type) { - case 'accounts': { - return getAllSerializedUIAccounts(); - } - case 'accountSources': { - return getAllSerializedUIAccountSources(); - } - default: { - throw new Error(`Unknown entity type ${type}`); - } - } - } -} diff --git a/apps/wallet/src/background/connections/index.ts b/apps/wallet/src/background/connections/index.ts deleted file mode 100644 index 82b01da16b31d..0000000000000 --- a/apps/wallet/src/background/connections/index.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage } from '_messages'; -import type { SetNetworkPayload } from '_payloads/network'; -import type { Permission } from '_payloads/permissions'; -import type { WalletStatusChange, WalletStatusChangePayload } from '_payloads/wallet-status-change'; -import type { NetworkEnvType } from '_src/shared/api-env'; -import { type UIAccessibleEntityType } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { type QredoConnectPayload } from '_src/shared/messaging/messages/payloads/QredoConnect'; -import Browser from 'webextension-polyfill'; - -import type { Connection } from './Connection'; -import { ContentScriptConnection } from './ContentScriptConnection'; -import { UiConnection } from './UiConnection'; - -const appOrigin = new URL(Browser.runtime.getURL('')).origin; - -export class Connections { - #connections: Connection[] = []; - - constructor() { - Browser.runtime.onConnect.addListener((port) => { - try { - let connection: Connection; - switch (port.name) { - case ContentScriptConnection.CHANNEL: - connection = new ContentScriptConnection(port); - break; - case UiConnection.CHANNEL: - if (port.sender?.origin !== appOrigin) { - throw new Error( - `[Connections] UI connections are not allowed for origin ${port.sender?.origin}`, - ); - } - connection = new UiConnection(port); - break; - default: - throw new Error(`[Connections] Unknown connection ${port.name}`); - } - this.#connections.push(connection); - connection.onDisconnect.subscribe(() => { - const connectionIndex = this.#connections.indexOf(connection); - if (connectionIndex >= 0) { - this.#connections.splice(connectionIndex, 1); - } - }); - } catch (e) { - port.disconnect(); - } - }); - } - - public notifyContentScript( - notification: - | { event: 'permissionReply'; permission: Permission } - | { - event: 'walletStatusChange'; - change: Omit; - } - | { - event: 'walletStatusChange'; - origin: string; - change: WalletStatusChange; - } - | { - event: 'qredoConnectResult'; - origin: string; - allowed: boolean; - }, - messageID?: string, - ) { - for (const aConnection of this.#connections) { - if (aConnection instanceof ContentScriptConnection) { - switch (notification.event) { - case 'permissionReply': - aConnection.permissionReply(notification.permission); - break; - case 'walletStatusChange': - if (!('origin' in notification) || aConnection.origin === notification.origin) { - aConnection.send( - createMessage({ - type: 'wallet-status-changed', - ...notification.change, - }), - ); - } - break; - case 'qredoConnectResult': - if (notification.origin === aConnection.origin) { - aConnection.send( - createMessage>( - { - type: 'qredo-connect', - method: 'connectResponse', - args: { allowed: notification.allowed }, - }, - messageID, - ), - ); - } - break; - } - } - } - } - - public notifyUI( - notification: - | { event: 'networkChanged'; network: NetworkEnvType } - | { event: 'storedEntitiesUpdated'; type: UIAccessibleEntityType }, - ) { - for (const aConnection of this.#connections) { - if (aConnection instanceof UiConnection) { - switch (notification.event) { - case 'networkChanged': - aConnection.send( - createMessage({ - type: 'set-network', - network: notification.network, - }), - ); - break; - case 'storedEntitiesUpdated': - aConnection.notifyEntitiesUpdated(notification.type); - break; - } - } - } - } -} diff --git a/apps/wallet/src/background/db.ts b/apps/wallet/src/background/db.ts deleted file mode 100644 index 967f5fd27ec54..0000000000000 --- a/apps/wallet/src/background/db.ts +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Dexie, { type Table } from 'dexie'; -import { exportDB, importDB } from 'dexie-export-import'; - -import { type AccountSourceSerialized } from './account-sources/AccountSource'; -import { type AccountType, type SerializedAccount } from './accounts/Account'; -import { captureException } from './sentry'; -import { getFromLocalStorage, setToLocalStorage } from './storage-utils'; - -const dbName = 'SuiWallet DB'; -const dbLocalStorageBackupKey = 'indexed-db-backup'; - -export const settingsKeys = { - isPopulated: 'isPopulated', - autoLockMinutes: 'auto-lock-minutes', -}; - -class DB extends Dexie { - accountSources!: Table; - accounts!: Table; - settings!: Table<{ value: boolean | number | null; setting: string }, string>; - - constructor() { - super(dbName); - this.version(1).stores({ - accountSources: 'id, type', - accounts: 'id, type, address, sourceID', - settings: 'setting', - }); - this.version(2).upgrade((transaction) => { - const zkLoginType: AccountType = 'zkLogin'; - transaction - .table('accounts') - .where({ type: 'zk' }) - .modify((anAccount) => { - anAccount.type = zkLoginType; - }); - }); - } -} - -async function init() { - const db = new DB(); - const isPopulated = !!(await db.settings.get(settingsKeys.isPopulated))?.value; - if (!isPopulated) { - try { - const backup = await getFromLocalStorage(dbLocalStorageBackupKey); - if (backup) { - captureException(new Error('IndexedDB is empty, attempting to restore from backup'), { - extra: { backupSize: backup.length }, - }); - await db.delete(); - (await importDB(new Blob([backup], { type: 'application/json' }))).close(); - await db.open(); - } - await db.settings.put({ setting: settingsKeys.isPopulated, value: true }); - } catch (e) { - captureException(e); - } - } - if (!db.isOpen()) { - await db.open(); - } - return db; -} -let initPromise: ReturnType | null = null; -export const getDB = () => { - if (!initPromise) { - initPromise = init(); - } - return initPromise; -}; - -export async function backupDB() { - try { - const backup = await (await exportDB(await getDB())).text(); - await setToLocalStorage(dbLocalStorageBackupKey, backup); - } catch (e) { - captureException(e); - } -} diff --git a/apps/wallet/src/background/index.ts b/apps/wallet/src/background/index.ts deleted file mode 100644 index aef9f0cb9b5ac..0000000000000 --- a/apps/wallet/src/background/index.ts +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { openInNewTab } from '_shared/utils'; -import { growthbook, setAttributes } from '_src/shared/experimentation/features'; -import { coerce, lte } from 'semver'; -import Browser from 'webextension-polyfill'; - -import { lockAllAccountSources } from './account-sources'; -import { accountSourcesEvents } from './account-sources/events'; -import { getAccountsStatusData, getAllAccounts, lockAllAccounts } from './accounts'; -import { accountsEvents } from './accounts/events'; -import Alarms, { autoLockAlarmName, cleanUpAlarmName } from './Alarms'; -import { Connections } from './connections'; -import NetworkEnv from './NetworkEnv'; -import Permissions from './Permissions'; -import * as Qredo from './qredo'; -import { initSentry } from './sentry'; -import Transactions from './Transactions'; - -growthbook.loadFeatures().catch(() => { - // silence the error -}); -initSentry(); - -Browser.runtime.onInstalled.addListener(async ({ reason, previousVersion }) => { - // Skip automatically opening the onboarding in end-to-end tests. - if (navigator.userAgent === 'Playwright') { - return; - } - Alarms.setCleanUpAlarm(); - // TODO: Our versions don't use semver, and instead are date-based. Instead of using the semver - // library, we can use some combination of parsing into a date + inspecting patch. - const previousVersionSemver = coerce(previousVersion)?.version; - if (reason === 'install') { - await Browser.storage.local.set({ - v: -1, - }); - openInNewTab(); - } else if (reason === 'update' && previousVersionSemver && lte(previousVersionSemver, '0.1.1')) { - // clear everything in the storage - // mainly done to clear the mnemonic that was stored - // as plain text - await Browser.storage.local.clear(); - await Browser.storage.local.set({ - v: -1, - }); - } else if (reason === 'update') { - const storageVersion = (await Browser.storage.local.get({ v: null })).v; - // handle address size update and include storage version - if (storageVersion === null) { - //clear permissions and active_account because currently they are using the previous address size - await Browser.storage.local.set({ - permissions: {}, - active_account: null, - v: -1, - }); - } - } -}); - -const connections = new Connections(); - -Permissions.permissionReply.subscribe((permission) => { - if (permission) { - connections.notifyContentScript({ - event: 'permissionReply', - permission, - }); - } -}); - -Permissions.on('connectedAccountsChanged', async ({ origin, accounts }) => { - connections.notifyContentScript({ - event: 'walletStatusChange', - origin, - change: { - accounts: await getAccountsStatusData(accounts), - }, - }); -}); - -accountsEvents.on('accountsChanged', async () => { - connections.notifyUI({ event: 'storedEntitiesUpdated', type: 'accounts' }); - await Permissions.ensurePermissionAccountsUpdated( - await Promise.all( - (await getAllAccounts()).map(async (anAccount) => ({ address: await anAccount.address })), - ), - ); -}); -accountsEvents.on('accountStatusChanged', () => { - connections.notifyUI({ event: 'storedEntitiesUpdated', type: 'accounts' }); -}); -accountsEvents.on('activeAccountChanged', () => { - connections.notifyUI({ event: 'storedEntitiesUpdated', type: 'accounts' }); -}); -accountSourcesEvents.on('accountSourceStatusUpdated', () => { - connections.notifyUI({ event: 'storedEntitiesUpdated', type: 'accountSources' }); -}); -accountSourcesEvents.on('accountSourcesChanged', () => { - connections.notifyUI({ event: 'storedEntitiesUpdated', type: 'accountSources' }); -}); - -Browser.alarms.onAlarm.addListener((alarm) => { - if (alarm.name === autoLockAlarmName) { - lockAllAccounts(); - lockAllAccountSources(); - } else if (alarm.name === cleanUpAlarmName) { - Transactions.clearStaleTransactions(); - } -}); - -NetworkEnv.getActiveNetwork().then(async ({ env, customRpcUrl }) => { - setAttributes({ - apiEnv: env, - customRPC: customRpcUrl, - }); -}); - -NetworkEnv.on('changed', async (network) => { - setAttributes({ - apiEnv: network.env, - customRPC: network.customRpcUrl, - }); - connections.notifyUI({ event: 'networkChanged', network }); - connections.notifyContentScript({ - event: 'walletStatusChange', - change: { network }, - }); -}); - -Browser.windows.onRemoved.addListener(async (id) => { - await Qredo.handleOnWindowClosed(id); -}); - -Qredo.onQredoEvent('onConnectionResponse', ({ allowed, request }) => { - request.messageIDs.forEach((aMessageID) => { - connections.notifyContentScript( - { - event: 'qredoConnectResult', - origin: request.origin, - allowed, - }, - aMessageID, - ); - }); -}); diff --git a/apps/wallet/src/background/legacy-accounts/LegacyVault.ts b/apps/wallet/src/background/legacy-accounts/LegacyVault.ts deleted file mode 100644 index f1498f4ab4780..0000000000000 --- a/apps/wallet/src/background/legacy-accounts/LegacyVault.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { decrypt } from '_shared/cryptography/keystore'; -import { - entropyToMnemonic, - mnemonicToEntropy, - toEntropy, - validateEntropy, -} from '_shared/utils/bip39'; -import { - fromExportedKeypair, - type LegacyExportedKeyPair, -} from '_shared/utils/from-exported-keypair'; -import { mnemonicToSeedHex, type Keypair } from '@mysten/sui/cryptography'; - -import { getFromLocalStorage } from '../storage-utils'; - -type StoredData = string | { v: 1 | 2; data: string }; - -type V2DecryptedDataType = { - entropy: string; - importedKeypairs: LegacyExportedKeyPair[]; - qredoTokens?: Record; - mnemonicSeedHex?: string; -}; - -const VAULT_KEY = 'vault'; - -export class LegacyVault { - public readonly entropy: Uint8Array; - public readonly importedKeypairs: Keypair[]; - public readonly qredoTokens: Map = new Map(); - public readonly mnemonicSeedHex: string; - - public static async fromLegacyStorage(password: string) { - const data = await getFromLocalStorage(VAULT_KEY); - if (!data) { - throw new Error('Wallet is not initialized'); - } - let entropy: Uint8Array | null = null; - let keypairs: Keypair[] = []; - let qredoTokens = new Map(); - let mnemonicSeedHex: string | null = null; - if (typeof data === 'string') { - entropy = mnemonicToEntropy( - // eslint-disable-next-line no-restricted-globals - Buffer.from(await decrypt(password, data)).toString('utf-8'), - ); - } else if (data.v === 1) { - entropy = toEntropy(await decrypt(password, data.data)); - } else if (data.v === 2) { - const { - entropy: entropySerialized, - importedKeypairs, - qredoTokens: storedTokens, - mnemonicSeedHex: storedMnemonicSeedHex, - } = await decrypt(password, data.data); - entropy = toEntropy(entropySerialized); - keypairs = importedKeypairs.map((aKeyPair) => fromExportedKeypair(aKeyPair, true)); - if (storedTokens) { - qredoTokens = new Map(Object.entries(storedTokens)); - } - mnemonicSeedHex = storedMnemonicSeedHex || null; - } else { - throw new Error("Unknown data, provided data can't be used to create a Vault"); - } - if (!validateEntropy(entropy)) { - throw new Error("Can't restore Vault, entropy is invalid."); - } - return new LegacyVault(entropy, keypairs, qredoTokens, mnemonicSeedHex); - } - - public static async isInitialized() { - return !!(await getFromLocalStorage(VAULT_KEY)); - } - - public static async verifyPassword(password: string) { - try { - await LegacyVault.fromLegacyStorage(password); - return true; - } catch (e) { - return false; - } - } - - constructor( - entropy: Uint8Array, - importedKeypairs: Keypair[] = [], - qredoTokens: Map = new Map(), - mnemonicSeedHex: string | null = null, - ) { - this.entropy = entropy; - this.importedKeypairs = importedKeypairs; - this.qredoTokens = qredoTokens; - this.mnemonicSeedHex = mnemonicSeedHex || mnemonicToSeedHex(entropyToMnemonic(entropy)); - } - - public getMnemonic() { - return entropyToMnemonic(this.entropy); - } -} diff --git a/apps/wallet/src/background/legacy-accounts/storage-migration.ts b/apps/wallet/src/background/legacy-accounts/storage-migration.ts deleted file mode 100644 index 7c9905d2f4161..0000000000000 --- a/apps/wallet/src/background/legacy-accounts/storage-migration.ts +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Dexie from 'dexie'; - -import { accountSourcesEvents } from '../account-sources/events'; -import { - deriveKeypairFromSeed, - makeDerivationPath, - MnemonicAccountSource, -} from '../account-sources/MnemonicAccountSource'; -import { QredoAccountSource } from '../account-sources/QredoAccountSource'; -import { type SerializedAccount } from '../accounts/Account'; -import { accountsEvents } from '../accounts/events'; -import { ImportedAccount } from '../accounts/ImportedAccount'; -import { LedgerAccount } from '../accounts/LedgerAccount'; -import { MnemonicAccount } from '../accounts/MnemonicAccount'; -import { type QredoSerializedAccount } from '../accounts/QredoAccount'; -import { backupDB, getDB } from '../db'; -import { type QredoConnection } from '../qredo/types'; -import { getFromLocalStorage, makeUniqueKey, setToLocalStorage } from '../storage-utils'; -import { LegacyVault } from './LegacyVault'; - -export type Status = 'required' | 'inProgress' | 'ready'; - -const migrationDoneStorageKey = 'storage-migration-done'; -const storageActiveAccountKey = 'active_account'; - -function getActiveAccountAddress() { - return getFromLocalStorage(storageActiveAccountKey); -} - -let statusCache: Status | null = null; - -export async function getStatus() { - if (statusCache) { - return statusCache; - } - const vaultInitialized = await LegacyVault.isInitialized(); - if (!vaultInitialized) { - return (statusCache = 'ready'); - } - const isMigrationDone = await getFromLocalStorage(migrationDoneStorageKey); - if (isMigrationDone) { - return (statusCache = 'ready'); - } - return (statusCache = 'required'); -} - -export function clearStatus() { - statusCache = null; -} - -async function makeMnemonicAccounts(password: string, vault: LegacyVault) { - const currentMnemonicIndex = (await getFromLocalStorage('last_account_index', 0)) || 0; - const mnemonicSource = await MnemonicAccountSource.createNew({ - password, - entropyInput: vault.entropy, - }); - const mnemonicAccounts = []; - for (let i = 0; i <= currentMnemonicIndex; i++) { - const derivationPath = makeDerivationPath(i); - const keyPair = deriveKeypairFromSeed(vault.mnemonicSeedHex, derivationPath); - mnemonicAccounts.push( - MnemonicAccount.createNew({ keyPair, derivationPath, sourceID: mnemonicSource.id }), - ); - } - return { mnemonicSource, mnemonicAccounts }; -} - -async function makeImportedAccounts(password: string, vault: LegacyVault) { - return Promise.all( - vault.importedKeypairs.map((keyPair) => - ImportedAccount.createNew({ password, keyPair: keyPair.getSecretKey() }), - ), - ); -} - -type LegacySerializedLedgerAccount = { - type: 'LEDGER'; - address: string; - derivationPath: string; - publicKey: string | null; -}; - -async function getSavedLedgerAccounts() { - const ledgerAccounts = await getFromLocalStorage( - 'imported_ledger_accounts', - [], - ); - return ledgerAccounts || []; -} - -async function makeLedgerAccounts(password: string) { - const ledgerAccounts = await getSavedLedgerAccounts(); - return Promise.all( - ledgerAccounts.map(({ address, derivationPath, publicKey }) => - LedgerAccount.createNew({ address, derivationPath, password, publicKey }), - ), - ); -} - -async function getAllLegacyStoredQredoConnections() { - return (await getFromLocalStorage('qredo-connections', [])) || []; -} - -async function makeQredoAccounts(password: string, vault: LegacyVault) { - const qredoSources = []; - const qredoAccounts: Omit[] = []; - for (const aQredoConnection of await getAllLegacyStoredQredoConnections()) { - const refreshToken = vault.qredoTokens.get(aQredoConnection.id); - if (!refreshToken) { - throw new Error( - `Failed to load qredo account (${aQredoConnection.id}), refresh token not found`, - ); - } - const aQredoSource = await QredoAccountSource.createNew({ - password, - apiUrl: aQredoConnection.apiUrl, - organization: aQredoConnection.organization, - origin: aQredoConnection.origin, - service: aQredoConnection.service, - refreshToken, - originFavIcon: aQredoConnection.originFavIcon || '', - }); - qredoSources.push(aQredoSource); - for (const aWallet of aQredoConnection.accounts) { - qredoAccounts.push({ - ...aWallet, - type: 'qredo', - lastUnlockedOn: null, - sourceID: aQredoSource.id, - selected: false, - nickname: null, - createdAt: Date.now(), - }); - } - } - return { qredoSources, qredoAccounts }; -} - -function withID>(anAccount: T) { - return { - ...anAccount, - id: makeUniqueKey(), - }; -} - -export async function doMigration(password: string) { - const legacyVault = await LegacyVault.fromLegacyStorage(password); - const currentStatus = await getStatus(); - if (currentStatus === 'required') { - statusCache = 'inProgress'; - try { - const db = await getDB(); - const currentActiveAccountAddress = await getActiveAccountAddress(); - const { mnemonicAccounts, mnemonicSource } = await makeMnemonicAccounts( - password, - legacyVault, - ); - const importedAccounts = await makeImportedAccounts(password, legacyVault); - const ledgerAccounts = await makeLedgerAccounts(password); - const { qredoAccounts, qredoSources } = await makeQredoAccounts(password, legacyVault); - await db.transaction('rw', db.accounts, db.accountSources, async () => { - await MnemonicAccountSource.save(mnemonicSource, { skipBackup: true, skipEventEmit: true }); - await db.accounts.bulkPut(mnemonicAccounts.map(withID)); - await db.accounts.bulkPut(importedAccounts.map(withID)); - await db.accounts.bulkPut(ledgerAccounts.map(withID)); - for (const aQredoSource of qredoSources) { - await QredoAccountSource.save(aQredoSource, { skipBackup: true, skipEventEmit: true }); - } - await db.accounts.bulkPut(qredoAccounts.map(withID)); - if (currentActiveAccountAddress) { - const accountToSetSelected = await db.accounts.get({ - address: currentActiveAccountAddress, - }); - if (accountToSetSelected) { - await db.accounts - .where('id') - .notEqual(accountToSetSelected.id) - .modify({ selected: false }); - await db.accounts.update(accountToSetSelected.id, { selected: true }); - } - } - await Dexie.waitFor(setToLocalStorage(migrationDoneStorageKey, true)); - }); - statusCache = 'ready'; - backupDB(); - accountSourcesEvents.emit('accountSourcesChanged'); - accountsEvents.emit('accountsChanged'); - } catch (e) { - statusCache = 'required'; - throw e; - } - } -} diff --git a/apps/wallet/src/background/qredo/index.ts b/apps/wallet/src/background/qredo/index.ts deleted file mode 100644 index 2ff1d45f1df0e..0000000000000 --- a/apps/wallet/src/background/qredo/index.ts +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type QredoConnectInput } from '_src/dapp-interface/WalletStandardInterface'; -import { type Message } from '_src/shared/messaging/messages'; -import { type QredoConnectPayload } from '_src/shared/messaging/messages/payloads/QredoConnect'; -import { QredoAPI } from '_src/shared/qredo-api'; -import mitt from 'mitt'; - -import { getQredoAccountSource } from '../account-sources'; -import { QredoAccountSource } from '../account-sources/QredoAccountSource'; -import { addNewAccounts } from '../accounts'; -import { type QredoAccount, type QredoSerializedAccount } from '../accounts/QredoAccount'; -import { type ContentScriptConnection } from '../connections/ContentScriptConnection'; -import Tabs from '../Tabs'; -import { Window } from '../Window'; -import { - createPendingRequest, - deletePendingRequest, - getAllPendingRequests, - getPendingRequest, - storeAllPendingRequests, - updatePendingRequest, -} from './storage'; -import { type QredoConnectPendingRequest, type UIQredoInfo } from './types'; -import { qredoConnectPageUrl, toUIQredoPendingRequest, validateInputOrThrow } from './utils'; - -const qredoEvents = mitt<{ - onConnectionResponse: { - allowed: boolean; - request: QredoConnectPendingRequest; - }; -}>(); - -export const onQredoEvent = qredoEvents.on; -export const offQredoEvent = qredoEvents.off; - -export async function requestUserApproval( - input: QredoConnectInput, - connection: ContentScriptConnection, - message: Message, -) { - const origin = connection.origin; - const { service, apiUrl, token, organization } = validateInputOrThrow(input); - const connectionIdentity = { - service, - apiUrl, - origin, - organization, - }; - const existingPendingRequest = await getPendingRequest(connectionIdentity); - if (existingPendingRequest) { - const qredoConnectUrl = qredoConnectPageUrl(existingPendingRequest.id); - const changes: Parameters['1'] = { - messageID: message.id, - append: true, - token: token, - }; - if ( - !(await Tabs.highlight({ - url: qredoConnectUrl, - windowID: existingPendingRequest.windowID || undefined, - match: ({ url, inAppRedirectUrl }) => { - const urlMatch = `/accounts/qredo-connect/${existingPendingRequest.id}`; - return ( - url.includes(urlMatch) || (!!inAppRedirectUrl && inAppRedirectUrl.includes(urlMatch)) - ); - }, - })) - ) { - const approvalWindow = new Window(qredoConnectUrl); - await approvalWindow.show(); - if (approvalWindow.id) { - changes.windowID = approvalWindow.id; - } - } - await updatePendingRequest(existingPendingRequest.id, changes); - return; - } - const request = await createPendingRequest( - { - service, - apiUrl, - token, - origin, - originFavIcon: connection.originFavIcon, - accessToken: null, - organization, - }, - message.id, - ); - const approvalWindow = new Window(qredoConnectPageUrl(request.id)); - await approvalWindow.show(); - if (approvalWindow.id) { - await updatePendingRequest(request.id, { windowID: approvalWindow.id }); - } -} - -export async function handleOnWindowClosed(windowID: number) { - const allRequests = await getAllPendingRequests(); - const remainingRequests: QredoConnectPendingRequest[] = []; - allRequests.forEach((aRequest) => { - if (aRequest.windowID === windowID) { - qredoEvents.emit('onConnectionResponse', { - allowed: false, - request: aRequest, - }); - } else { - remainingRequests.push(aRequest); - } - }); - if (allRequests.length !== remainingRequests.length) { - await storeAllPendingRequests(remainingRequests); - } -} - -export async function getUIQredoPendingRequest(requestID: string) { - const pendingRequest = await getPendingRequest(requestID); - if (pendingRequest) { - return toUIQredoPendingRequest(pendingRequest); - } - return null; -} - -const IN_PROGRESS_ACCESS_TOKENS_RENEWALS: Record | null> = {}; - -async function renewAccessToken( - qredoInfo: { requestID: string; apiUrl: string; refreshToken: string } | QredoAccountSource, -) { - let accessToken: string; - const isPendingRequest = !(qredoInfo instanceof QredoAccountSource); - const requestID = isPendingRequest ? qredoInfo.requestID : qredoInfo.id; - if (!IN_PROGRESS_ACCESS_TOKENS_RENEWALS[requestID]) { - IN_PROGRESS_ACCESS_TOKENS_RENEWALS[requestID] = isPendingRequest - ? new QredoAPI(requestID, qredoInfo.apiUrl) - .createAccessToken({ refreshToken: qredoInfo.refreshToken }) - .then(({ access_token }) => access_token) - .finally(() => (IN_PROGRESS_ACCESS_TOKENS_RENEWALS[requestID] = null)) - : qredoInfo.renewAccessToken(); - accessToken = (await IN_PROGRESS_ACCESS_TOKENS_RENEWALS[requestID])!; - if (isPendingRequest) { - await updatePendingRequest(requestID, { accessToken }); - } - } else { - accessToken = (await IN_PROGRESS_ACCESS_TOKENS_RENEWALS[requestID])!; - } - return accessToken; -} - -// This function returns the connection info for the UI and creates an access token when it doesn't exist or if is forced to be created. -// Because pending and existing connections never have the same ID this function fetches data for either of them based on the id. -export async function getUIQredoInfo( - qredoID: string, - forceRenewAccessToken: boolean, -): Promise { - const pendingRequest = await getPendingRequest(qredoID); - const existingConnection = pendingRequest ? null : await getQredoAccountSource(qredoID); - if (!pendingRequest && !existingConnection) { - return null; - } - const { id, service, apiUrl } = (pendingRequest || existingConnection)!; - const refreshToken = pendingRequest - ? pendingRequest.token - : await existingConnection!.refreshToken; - let accessToken = pendingRequest?.accessToken || existingConnection?.accessToken || null; - if (forceRenewAccessToken || !accessToken) { - if (!refreshToken) { - return null; - } - accessToken = await renewAccessToken( - existingConnection || { requestID: id, apiUrl: await apiUrl, refreshToken }, - ); - } - return { - id, - service: await service, - apiUrl: await apiUrl, - accessToken: await accessToken, - }; -} - -export async function rejectQredoConnection({ - qredoID, -}: QredoConnectPayload<'rejectQredoConnection'>['args']) { - const pendingRequest = await getPendingRequest(qredoID); - if (pendingRequest) { - await deletePendingRequest(pendingRequest); - qredoEvents.emit('onConnectionResponse', { - allowed: false, - request: pendingRequest, - }); - } -} - -export async function acceptQredoConnection({ - qredoID, - password, - accounts, -}: QredoConnectPayload<'acceptQredoConnection'>['args']) { - const pendingRequest = await getPendingRequest(qredoID); - if (!pendingRequest) { - throw new Error(`Accepting Qredo connection failed, pending request ${qredoID} not found`); - } - const { apiUrl, origin, originFavIcon, service, organization } = pendingRequest; - const connectionIdentity = { - apiUrl, - origin, - service, - organization, - }; - // make sure we replace an existing connection when it's the same - let qredoAccountSource = await getQredoAccountSource(connectionIdentity); - if (!qredoAccountSource) { - qredoAccountSource = await QredoAccountSource.save( - await QredoAccountSource.createNew({ - password, - apiUrl, - origin, - organization, - refreshToken: pendingRequest.token, - service, - originFavIcon: originFavIcon || '', - }), - ); - } - if (!(await qredoAccountSource.isLocked())) { - // credentials are kept in session storage, force renewal - await qredoAccountSource.unlock(password); - } - const newQredoAccounts: Omit[] = []; - for (const aWallet of accounts) { - newQredoAccounts.push({ - ...aWallet, - type: 'qredo', - sourceID: qredoAccountSource.id, - lastUnlockedOn: null, - selected: false, - nickname: null, - createdAt: Date.now(), - }); - } - const connectedAccounts = (await addNewAccounts(newQredoAccounts)) as QredoAccount[]; - await deletePendingRequest(pendingRequest); - qredoEvents.emit('onConnectionResponse', { - allowed: true, - request: pendingRequest, - }); - return Promise.all(connectedAccounts.map(async (anAccount) => await anAccount.toUISerialized())); -} diff --git a/apps/wallet/src/background/qredo/storage.ts b/apps/wallet/src/background/qredo/storage.ts deleted file mode 100644 index 30a017c2beaa9..0000000000000 --- a/apps/wallet/src/background/qredo/storage.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { v4 as uuid } from 'uuid'; - -import { - getFromSessionStorage, - isSessionStorageSupported, - setToSessionStorage, -} from '../storage-utils'; -import type { QredoConnectIdentity, QredoConnectPendingRequest } from './types'; -import { isSameQredoConnection } from './utils'; - -const SESSION_STORAGE_KEY = 'qredo-connect-requests'; - -function sessionStorageAssert() { - if (!isSessionStorageSupported()) { - throw new Error('Session storage is required. Please update your browser'); - } -} - -export async function getAllPendingRequests() { - sessionStorageAssert(); - return (await getFromSessionStorage(SESSION_STORAGE_KEY, [])) || []; -} - -export function storeAllPendingRequests(requests: QredoConnectPendingRequest[]) { - sessionStorageAssert(); - return setToSessionStorage(SESSION_STORAGE_KEY, requests); -} - -export async function getPendingRequest(requestIdentity: QredoConnectIdentity | string) { - return ( - (await getAllPendingRequests()).find((aRequest) => - isSameQredoConnection(requestIdentity, aRequest), - ) || null - ); -} - -async function storePendingRequest(request: QredoConnectPendingRequest) { - const allPendingRequests = await getAllPendingRequests(); - const existingIndex = allPendingRequests.findIndex((aRequest) => aRequest.id === request.id); - if (existingIndex >= 0) { - allPendingRequests.splice(existingIndex, 1, request); - } else { - allPendingRequests.push(request); - } - await storeAllPendingRequests(allPendingRequests); -} - -export async function deletePendingRequest(request: QredoConnectPendingRequest) { - await storeAllPendingRequests( - (await getAllPendingRequests()).filter(({ id }) => request.id !== id), - ); -} - -export async function createPendingRequest( - options: Omit, - messageID: string, -) { - const newRequest: QredoConnectPendingRequest = { - ...options, - id: uuid(), - windowID: null, - messageIDs: [messageID], - }; - await storePendingRequest(newRequest); - return newRequest; -} - -export async function updatePendingRequest( - id: string, - change: { - windowID?: number; - messageID?: string; - append?: boolean; - token?: string; - accessToken?: string; - }, -) { - const request = await getPendingRequest(id); - if (!request) { - return; - } - if (typeof change.windowID === 'number') { - request.windowID = change.windowID; - } - if (change.messageID) { - if (change.append) { - request.messageIDs.push(change.messageID); - } else { - request.messageIDs = [change.messageID]; - } - } - if (change.token) { - request.token = change.token; - } - if (change.accessToken) { - request.accessToken = change.accessToken; - } - await storePendingRequest(request); -} diff --git a/apps/wallet/src/background/qredo/types.ts b/apps/wallet/src/background/qredo/types.ts deleted file mode 100644 index e4c57b3a46076..0000000000000 --- a/apps/wallet/src/background/qredo/types.ts +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Wallet } from '_src/shared/qredo-api'; - -export type QredoConnectIdentity = { - service: string; - apiUrl: string; - origin: string; - /** this was renamed to workspace in qredo side but keeping it as organization in wallet to avoid further changes */ - organization: string; -}; - -export type QredoConnectPendingRequest = { - id: string; - originFavIcon?: string; - token: string; - windowID: number | null; - messageIDs: string[]; - accessToken: string | null; -} & QredoConnectIdentity; - -export type UIQredoPendingRequest = Pick< - QredoConnectPendingRequest, - 'id' | 'service' | 'apiUrl' | 'origin' | 'originFavIcon' | 'organization' -> & { partialToken: `…${string}` }; - -export type UIQredoInfo = { - id: string; - accessToken: string | null; - apiUrl: string; - service: string; -}; - -export type QredoConnection = Omit< - QredoConnectPendingRequest, - 'token' | 'windowID' | 'messageIDs' -> & { - accounts: Wallet[]; - accessToken: string | null; -}; diff --git a/apps/wallet/src/background/qredo/utils.ts b/apps/wallet/src/background/qredo/utils.ts deleted file mode 100644 index b60f170da833c..0000000000000 --- a/apps/wallet/src/background/qredo/utils.ts +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type QredoConnectInput } from '_src/dapp-interface/WalletStandardInterface'; -import Browser from 'webextension-polyfill'; - -import { - type QredoConnectIdentity, - type QredoConnectPendingRequest, - type UIQredoPendingRequest, -} from './types'; - -export function qredoConnectPageUrl(requestID: string) { - return `${Browser.runtime.getURL('ui.html')}#/accounts/qredo-connect/${encodeURIComponent( - requestID, - )}`; -} - -export function trimString(input: unknown) { - return (typeof input === 'string' && input.trim()) || ''; -} - -export function validateInputOrThrow(input: QredoConnectInput) { - if (!input) { - throw new Error('Invalid Qredo connect parameters'); - } - let apiUrl; - try { - apiUrl = new URL(input.apiUrl); - if (!['http:', 'https:'].includes(apiUrl.protocol)) { - throw new Error('Only https (or http) is supported'); - } - } catch (e) { - throw new Error(`Not valid apiUrl. ${(e as Error).message}`); - } - const service = trimString(input.service); - if (!service) { - throw new Error('Invalid service name'); - } - const token = trimString(input.token); - if (!token) { - throw new Error('Invalid token'); - } - return { - service, - apiUrl: apiUrl.toString(), - token, - organization: trimString('organization' in input ? input.organization : input.workspace), - }; -} - -const UI_TOKEN_MAX_LENGTH = 8; - -export function toUIQredoPendingRequest(stored: QredoConnectPendingRequest): UIQredoPendingRequest { - return { - id: stored.id, - service: stored.service, - apiUrl: stored.apiUrl, - origin: stored.origin, - originFavIcon: stored.originFavIcon, - partialToken: `…${stored.token.slice(-UI_TOKEN_MAX_LENGTH)}`, - organization: stored.organization || '', - }; -} - -export function isSameQredoConnection< - T1 extends QredoConnectIdentity | string, - T2 extends QredoConnectIdentity & { id: string }, ->(a: T1, b: T2) { - return ( - (typeof a === 'string' && b.id === a) || - (typeof a === 'object' && - a.apiUrl === b.apiUrl && - a.origin === b.origin && - a.service === b.service && - a.organization === b.organization) - ); -} diff --git a/apps/wallet/src/background/sentry.ts b/apps/wallet/src/background/sentry.ts deleted file mode 100644 index 92b30158f614c..0000000000000 --- a/apps/wallet/src/background/sentry.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { growthbook } from '_src/shared/experimentation/features'; -import { getSentryConfig } from '_src/shared/sentry-config'; -import * as Sentry from '@sentry/browser'; - -export function initSentry() { - Sentry.addTracingExtensions(); - Sentry.init( - getSentryConfig({ - tracesSampler: () => { - return growthbook.getFeatureValue('wallet-sentry-tracing', 0); - }, - }), - ); -} - -export const captureException = Sentry.captureException; -export const captureMessage = Sentry.captureMessage; diff --git a/apps/wallet/src/background/session-ephemeral-values.ts b/apps/wallet/src/background/session-ephemeral-values.ts deleted file mode 100644 index 36e2b8a110460..0000000000000 --- a/apps/wallet/src/background/session-ephemeral-values.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Serializable } from '_shared/cryptography/keystore'; -import { - getEncryptedFromSessionStorage, - removeFromSessionStorage, - setToSessionStorageEncrypted, -} from '_src/background/storage-utils'; - -export function getEphemeralValue(id: string) { - return getEncryptedFromSessionStorage(id); -} - -export function setEphemeralValue(id: string, data: T) { - return setToSessionStorageEncrypted(id, data); -} - -export function clearEphemeralValue(id: string) { - return removeFromSessionStorage(id); -} diff --git a/apps/wallet/src/background/storage-utils.ts b/apps/wallet/src/background/storage-utils.ts deleted file mode 100644 index abda9454c58b8..0000000000000 --- a/apps/wallet/src/background/storage-utils.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - decrypt, - encrypt, - getRandomPassword, - makeEphemeraPassword, - type Serializable, -} from '_src/shared/cryptography/keystore'; -import { v4 as uuidV4 } from 'uuid'; -import Browser from 'webextension-polyfill'; -import type { Storage } from 'webextension-polyfill'; - -const SESSION_STORAGE: Storage.LocalStorageArea | null = - // @ts-expect-error chrome - global?.chrome?.storage?.session || null; - -async function getFromStorage( - storage: Storage.LocalStorageArea, - key: string, - defaultValue: T | null = null, -): Promise { - return (await storage.get({ [key]: defaultValue }))[key]; -} - -async function setToStorage( - storage: Storage.LocalStorageArea, - key: string, - value: T, -): Promise { - return await storage.set({ [key]: value }); -} - -export function isSessionStorageSupported() { - return !!SESSION_STORAGE; -} - -//eslint-disable-next-line @typescript-eslint/no-explicit-any -type OmitFirst = T extends [any, ...infer R] ? R : never; -type GetParams = OmitFirst>>; -type SetParams = OmitFirst>>; - -export function getFromLocalStorage(...params: GetParams) { - return getFromStorage(Browser.storage.local, ...params); -} -export function setToLocalStorage(...params: SetParams) { - return setToStorage(Browser.storage.local, ...params); -} -export async function getFromSessionStorage(...params: GetParams) { - if (!SESSION_STORAGE) { - return null; - } - return getFromStorage(SESSION_STORAGE, ...params); -} -export async function setToSessionStorage(...params: SetParams) { - if (!SESSION_STORAGE) { - return; - } - return setToStorage(SESSION_STORAGE, ...params); -} -export async function removeFromSessionStorage(key: string) { - if (!SESSION_STORAGE) { - return; - } - await SESSION_STORAGE.remove(key); -} -export async function setToSessionStorageEncrypted(key: string, value: T) { - const random = getRandomPassword(); - await setToSessionStorage(key, { - random, - data: await encrypt(makeEphemeraPassword(random), value), - }); -} -export async function getEncryptedFromSessionStorage(key: string) { - const encryptedData = await getFromSessionStorage<{ random: string; data: string }>(key, null); - if (!encryptedData) { - return null; - } - try { - return decrypt(makeEphemeraPassword(encryptedData.random), encryptedData.data); - } catch (e) { - return null; - } -} - -/** - * Generates a unique id using uuid, that can be used as a key for storage data - */ -export function makeUniqueKey() { - return uuidV4(); -} diff --git a/apps/wallet/src/content-script/index.ts b/apps/wallet/src/content-script/index.ts deleted file mode 100644 index 03a0e8d64ea96..0000000000000 --- a/apps/wallet/src/content-script/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { injectDappInterface } from './interface-inject'; -import { setupMessagesProxy } from './messages-proxy'; - -injectDappInterface(); -setupMessagesProxy(); diff --git a/apps/wallet/src/content-script/interface-inject.ts b/apps/wallet/src/content-script/interface-inject.ts deleted file mode 100644 index 92efd1b13c477..0000000000000 --- a/apps/wallet/src/content-script/interface-inject.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Browser from 'webextension-polyfill'; - -export function injectDappInterface() { - const script = document.createElement('script'); - script.setAttribute('src', Browser.runtime.getURL('dapp-interface.js')); - const container = document.head || document.documentElement; - container.insertBefore(script, container.firstElementChild); - container.removeChild(script); -} diff --git a/apps/wallet/src/content-script/messages-proxy.ts b/apps/wallet/src/content-script/messages-proxy.ts deleted file mode 100644 index aabede06ac613..0000000000000 --- a/apps/wallet/src/content-script/messages-proxy.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { PortStream } from '_messaging/PortStream'; -import { WindowMessageStream } from '_messaging/WindowMessageStream'; -import type { Message } from '_src/shared/messaging/messages'; -import { take } from 'rxjs'; - -function createPort(windowMsgStream: WindowMessageStream, currentMsg?: Message) { - const port = PortStream.connectToBackgroundService('sui_content<->background'); - if (currentMsg) { - port.sendMessage(currentMsg); - } - port.onMessage.subscribe((msg) => { - windowMsgStream.send(msg); - }); - const windowMsgSub = windowMsgStream.messages.subscribe((msg) => { - port.sendMessage(msg); - }); - port.onDisconnect.subscribe((port) => { - windowMsgSub.unsubscribe(); - createPort(windowMsgStream); - }); -} - -export function setupMessagesProxy() { - const windowMsgStream = new WindowMessageStream('sui_content-script', 'sui_in-page'); - windowMsgStream.messages.pipe(take(1)).subscribe((msg) => { - createPort(windowMsgStream, msg); - }); -} diff --git a/apps/wallet/src/dapp-interface/WalletStandardInterface.ts b/apps/wallet/src/dapp-interface/WalletStandardInterface.ts deleted file mode 100644 index 7350a5b88f151..0000000000000 --- a/apps/wallet/src/dapp-interface/WalletStandardInterface.ts +++ /dev/null @@ -1,467 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage } from '_messages'; -import { WindowMessageStream } from '_messaging/WindowMessageStream'; -import type { BasePayload, Payload } from '_payloads'; -import type { GetAccount } from '_payloads/account/GetAccount'; -import type { GetAccountResponse } from '_payloads/account/GetAccountResponse'; -import type { SetNetworkPayload } from '_payloads/network'; -import { - ALL_PERMISSION_TYPES, - type AcquirePermissionsRequest, - type AcquirePermissionsResponse, - type HasPermissionsRequest, - type HasPermissionsResponse, -} from '_payloads/permissions'; -import type { - ExecuteTransactionRequest, - ExecuteTransactionResponse, - SignTransactionRequest, - SignTransactionResponse, -} from '_payloads/transactions'; -import { API_ENV } from '_src/shared/api-env'; -import type { NetworkEnvType } from '_src/shared/api-env'; -import { type DisconnectApp } from '_src/shared/messaging/messages/payloads/permissions/DisconnectApp'; -import { - isQredoConnectPayload, - type QredoConnectPayload, -} from '_src/shared/messaging/messages/payloads/QredoConnect'; -import { type SignMessageRequest } from '_src/shared/messaging/messages/payloads/transactions/SignMessage'; -import { isWalletStatusChangePayload } from '_src/shared/messaging/messages/payloads/wallet-status-change'; -import { bcs } from '@mysten/sui/bcs'; -import { isTransaction } from '@mysten/sui/transactions'; -import { fromBase64, toBase64 } from '@mysten/sui/utils'; -import { - ReadonlyWalletAccount, - SUI_CHAINS, - SUI_DEVNET_CHAIN, - SUI_LOCALNET_CHAIN, - SUI_MAINNET_CHAIN, - SUI_TESTNET_CHAIN, - type StandardConnectFeature, - type StandardConnectMethod, - type StandardDisconnectFeature, - type StandardDisconnectMethod, - type StandardEventsFeature, - type StandardEventsListeners, - type StandardEventsOnMethod, - type SuiFeatures, - type SuiSignAndExecuteTransactionBlockMethod, - type SuiSignAndExecuteTransactionMethod, - type SuiSignMessageMethod, - type SuiSignPersonalMessageMethod, - type SuiSignTransactionBlockMethod, - type SuiSignTransactionMethod, - type Wallet, -} from '@mysten/wallet-standard'; -import mitt, { type Emitter } from 'mitt'; -import { filter, map, type Observable } from 'rxjs'; - -import { mapToPromise } from './utils'; - -type WalletEventsMap = { - [E in keyof StandardEventsListeners]: Parameters[0]; -}; - -// NOTE: Because this runs in a content script, we can't fetch the manifest. -const name = process.env.APP_NAME || 'Sui Wallet'; - -export type QredoConnectInput = { - service: string; - apiUrl: string; - token: string; -} & ( - | { - /** @deprecated renamed to workspace, please use that */ - organization: string; - } - | { - workspace: string; - } -); - -type QredoConnectFeature = { - 'qredo:connect': { - version: '0.0.1'; - qredoConnect: (input: QredoConnectInput) => Promise; - }; -}; -type ChainType = Wallet['chains'][number]; -const API_ENV_TO_CHAIN: Record, ChainType> = { - [API_ENV.local]: SUI_LOCALNET_CHAIN, - [API_ENV.devNet]: SUI_DEVNET_CHAIN, - [API_ENV.testNet]: SUI_TESTNET_CHAIN, - [API_ENV.mainnet]: SUI_MAINNET_CHAIN, -}; - -export class SuiWallet implements Wallet { - readonly #events: Emitter; - readonly #version = '1.0.0' as const; - readonly #name = name; - #accounts: ReadonlyWalletAccount[]; - #messagesStream: WindowMessageStream; - #activeChain: ChainType | null = null; - - get version() { - return this.#version; - } - - get name() { - return this.#name; - } - - get icon() { - return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxyZWN0IHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgZmlsbD0iIzRDQTNGRiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xOC44MzI3IDEyLjM0MTNWMTIuMzQyMkMxOS42NDgyIDEzLjM2NTMgMjAuMTM2IDE0LjY2MTMgMjAuMTM2IDE2LjA3MDVDMjAuMTM2IDE3LjQ3OTggMTkuNjMzNyAxOC44MTQzIDE4Ljc5NTcgMTkuODQ0M0wxOC43MjM1IDE5LjkzM0wxOC43MDQ1IDE5LjgyMDNDMTguNjg4MiAxOS43MjQ1IDE4LjY2OSAxOS42Mjc1IDE4LjY0NyAxOS41M0MxOC4yMjc3IDE3LjY4NzUgMTYuODYxMiAxNi4xMDc1IDE0LjYxMjUgMTQuODI4MkMxMy4wOTQgMTMuOTY2OCAxMi4yMjQ3IDEyLjkyOTIgMTEuOTk2NSAxMS43NTA4QzExLjg0OSAxMC45ODg1IDExLjk1ODcgMTAuMjIzIDEyLjE3MDUgOS41NjcyNUMxMi4zODIyIDguOTExNzUgMTIuNjk3MiA4LjM2MjUgMTIuOTY0NyA4LjAzMkwxMy44Mzk1IDYuOTYyMjVDMTMuOTkzIDYuNzc0NzUgMTQuMjggNi43NzQ3NSAxNC40MzM1IDYuOTYyMjVMMTguODMzIDEyLjM0MTVMMTguODMyNyAxMi4zNDEzWk0yMC4yMTY1IDExLjI3MjVWMTEuMjcyTDE0LjM1MyA0LjEwMjc1QzE0LjI0MSAzLjk2NTc1IDE0LjAzMTUgMy45NjU3NSAxMy45MTk1IDQuMTAyNzVMOC4wNTYgMTEuMjcyM1YxMS4yNzI4TDguMDM3IDExLjI5NjVDNi45NTgyNSAxMi42MzUzIDYuMzEyNSAxNC4zMzY4IDYuMzEyNSAxNi4xODlDNi4zMTI1IDIwLjUwMjggOS44MTUyNSAyNCAxNC4xMzYzIDI0QzE4LjQ1NzIgMjQgMjEuOTYgMjAuNTAyOCAyMS45NiAxNi4xODlDMjEuOTYgMTQuMzM2OCAyMS4zMTQyIDEyLjYzNTMgMjAuMjM1MiAxMS4yOTYzTDIwLjIxNiAxMS4yNzI1SDIwLjIxNjVaTTkuNDU5MjUgMTIuMzE4TDkuOTgzNzUgMTEuNjc2NUw5Ljk5OTUgMTEuNzk1QzEwLjAxMiAxMS44ODg3IDEwLjAyNzIgMTEuOTgzIDEwLjA0NTIgMTIuMDc3OEMxMC4zODQ1IDEzLjg1ODIgMTEuNTk2NyAxNS4zNDI4IDEzLjYyMzUgMTYuNDkyNUMxNS4zODUyIDE3LjQ5NSAxNi40MTEgMTguNjQ4IDE2LjcwNjUgMTkuOTEyNUMxNi44Mjk4IDIwLjQ0MDMgMTYuODUxNyAyMC45NTk1IDE2Ljc5ODUgMjEuNDEzNUwxNi43OTUyIDIxLjQ0MTVMMTYuNzY5NyAyMS40NTRDMTUuOTc0NyAyMS44NDI1IDE1LjA4MDcgMjIuMDYwNSAxNC4xMzYgMjIuMDYwNUMxMC44MjI1IDIyLjA2MDUgOC4xMzYyNSAxOS4zNzg4IDguMTM2MjUgMTYuMDcwNUM4LjEzNjI1IDE0LjY1MDMgOC42MzE1IDEzLjM0NSA5LjQ1OSAxMi4zMTgzTDkuNDU5MjUgMTIuMzE4WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==' as const; - } - - get chains() { - // TODO: Extract chain from wallet: - return SUI_CHAINS; - } - - get features(): StandardConnectFeature & - StandardEventsFeature & - StandardDisconnectFeature & - SuiFeatures & - QredoConnectFeature { - return { - 'standard:connect': { - version: '1.0.0', - connect: this.#connect, - }, - 'standard:events': { - version: '1.0.0', - on: this.#on, - }, - 'standard:disconnect': { - version: '1.0.0', - disconnect: this.#disconnect, - }, - 'sui:signTransactionBlock': { - version: '1.0.0', - signTransactionBlock: this.#signTransactionBlock, - }, - 'sui:signTransaction': { - version: '2.0.0', - signTransaction: this.#signTransaction, - }, - 'sui:signAndExecuteTransactionBlock': { - version: '1.0.0', - signAndExecuteTransactionBlock: this.#signAndExecuteTransactionBlock, - }, - 'sui:signAndExecuteTransaction': { - version: '2.0.0', - signAndExecuteTransaction: this.#signAndExecuteTransaction, - }, - 'sui:signMessage': { - version: '1.0.0', - signMessage: this.#signMessage, - }, - 'sui:signPersonalMessage': { - version: '1.0.0', - signPersonalMessage: this.#signPersonalMessage, - }, - 'qredo:connect': { - version: '0.0.1', - qredoConnect: this.#qredoConnect, - }, - }; - } - - get accounts() { - return this.#accounts; - } - - #setAccounts(accounts: GetAccountResponse['accounts']) { - this.#accounts = accounts.map( - ({ address, publicKey, nickname }) => - new ReadonlyWalletAccount({ - address, - label: nickname || undefined, - publicKey: publicKey ? fromBase64(publicKey) : new Uint8Array(), - chains: this.#activeChain ? [this.#activeChain] : [], - features: ['sui:signAndExecuteTransaction'], - }), - ); - } - - constructor() { - this.#events = mitt(); - this.#accounts = []; - this.#messagesStream = new WindowMessageStream('sui_in-page', 'sui_content-script'); - this.#messagesStream.messages.subscribe(({ payload }) => { - if (isWalletStatusChangePayload(payload)) { - const { network, accounts } = payload; - if (network) { - this.#setActiveChain(network); - if (!accounts) { - // in case an accounts change exists skip updating chains of current accounts - // accounts will be updated in the if block below - this.#accounts = this.#accounts.map( - ({ address, features, icon, label, publicKey }) => - new ReadonlyWalletAccount({ - address, - publicKey, - chains: this.#activeChain ? [this.#activeChain] : [], - features, - label, - icon, - }), - ); - } - } - if (accounts) { - this.#setAccounts(accounts); - } - this.#events.emit('change', { accounts: this.accounts }); - } - }); - } - - #on: StandardEventsOnMethod = (event, listener) => { - this.#events.on(event, listener); - return () => this.#events.off(event, listener); - }; - - #connected = async () => { - this.#setActiveChain(await this.#getActiveNetwork()); - if (!(await this.#hasPermissions(['viewAccount']))) { - return; - } - const accounts = await this.#getAccounts(); - this.#setAccounts(accounts); - if (this.#accounts.length) { - this.#events.emit('change', { accounts: this.accounts }); - } - }; - - #connect: StandardConnectMethod = async (input) => { - if (!input?.silent) { - await mapToPromise( - this.#send({ - type: 'acquire-permissions-request', - permissions: ALL_PERMISSION_TYPES, - }), - (response) => response.result, - ); - } - - await this.#connected(); - - return { accounts: this.accounts }; - }; - - #disconnect: StandardDisconnectMethod = async () => { - this.#send({ - type: 'disconnect-app', - origin: '', // origin is auto-discovered for wallet's disconnect. - }); - }; - - #signTransactionBlock: SuiSignTransactionBlockMethod = async ({ - transactionBlock, - account, - ...input - }) => { - if (!isTransaction(transactionBlock)) { - throw new Error( - 'Unexpected transaction format found. Ensure that you are using the `Transaction` class.', - ); - } - - return mapToPromise( - this.#send({ - type: 'sign-transaction-request', - transaction: { - ...input, - // account might be undefined if previous version of adapters is used - // in that case use the first account address - account: account?.address || this.#accounts[0]?.address || '', - transaction: transactionBlock.serialize(), - }, - }), - (response) => response.result, - ); - }; - - #signTransaction: SuiSignTransactionMethod = async ({ transaction, account, ...input }) => { - return mapToPromise( - this.#send({ - type: 'sign-transaction-request', - transaction: { - ...input, - // account might be undefined if previous version of adapters is used - // in that case use the first account address - account: account?.address || this.#accounts[0]?.address || '', - transaction: await transaction.toJSON(), - }, - }), - ({ result: { signature, transactionBlockBytes: bytes } }) => ({ - signature, - bytes, - }), - ); - }; - - #signAndExecuteTransactionBlock: SuiSignAndExecuteTransactionBlockMethod = async (input) => { - if (!isTransaction(input.transactionBlock)) { - throw new Error( - 'Unexpected transaction format found. Ensure that you are using the `Transaction` class.', - ); - } - - return mapToPromise( - this.#send({ - type: 'execute-transaction-request', - transaction: { - type: 'transaction', - data: input.transactionBlock.serialize(), - options: input.options, - // account might be undefined if previous version of adapters is used - // in that case use the first account address - account: input.account?.address || this.#accounts[0]?.address || '', - }, - }), - (response) => response.result, - ); - }; - - #signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async (input) => { - return mapToPromise( - this.#send({ - type: 'execute-transaction-request', - transaction: { - type: 'transaction', - data: await input.transaction.toJSON(), - options: { - showRawEffects: true, - showRawInput: true, - }, - // account might be undefined if previous version of adapters is used - // in that case use the first account address - account: input.account?.address || this.#accounts[0]?.address || '', - }, - }), - ({ result: { rawEffects, rawTransaction, digest } }) => { - const [ - { - txSignatures: [signature], - intentMessage: { value: bcsTransaction }, - }, - ] = bcs.SenderSignedData.parse(fromBase64(rawTransaction!)); - - const bytes = bcs.TransactionData.serialize(bcsTransaction).toBase64(); - - return { - digest, - signature, - bytes, - effects: toBase64(new Uint8Array(rawEffects!)), - }; - }, - ); - }; - - #signMessage: SuiSignMessageMethod = async ({ message, account }) => { - return mapToPromise( - this.#send({ - type: 'sign-message-request', - args: { - message: toBase64(message), - accountAddress: account.address, - }, - }), - (response) => { - if (!response.return) { - throw new Error('Invalid sign message response'); - } - return response.return; - }, - ); - }; - - #signPersonalMessage: SuiSignPersonalMessageMethod = async ({ message, account }) => { - return mapToPromise( - this.#send({ - type: 'sign-message-request', - args: { - message: toBase64(message), - accountAddress: account.address, - }, - }), - (response) => { - if (!response.return) { - throw new Error('Invalid sign message response'); - } - return { - bytes: response.return.messageBytes, - signature: response.return.signature, - }; - }, - ); - }; - - #hasPermissions(permissions: HasPermissionsRequest['permissions']) { - return mapToPromise( - this.#send({ - type: 'has-permissions-request', - permissions: permissions, - }), - ({ result }) => result, - ); - } - - #getAccounts() { - return mapToPromise( - this.#send({ - type: 'get-account', - }), - (response) => response.accounts, - ); - } - - #getActiveNetwork() { - return mapToPromise( - this.#send({ - type: 'get-network', - }), - ({ network }) => network, - ); - } - - #setActiveChain({ env }: NetworkEnvType) { - this.#activeChain = env === API_ENV.customRPC ? 'sui:unknown' : API_ENV_TO_CHAIN[env]; - } - - #qredoConnect = async (input: QredoConnectInput): Promise => { - const allowed = await mapToPromise( - this.#send, QredoConnectPayload<'connectResponse'>>({ - type: 'qredo-connect', - method: 'connect', - args: { ...input }, - }), - (response) => { - if (!isQredoConnectPayload(response, 'connectResponse')) { - throw new Error('Invalid qredo connect response'); - } - return response.args.allowed; - }, - ); - if (!allowed) { - throw new Error('Rejected by user'); - } - }; - - #send( - payload: RequestPayload, - responseForID?: string, - ): Observable { - const msg = createMessage(payload, responseForID); - this.#messagesStream.send(msg); - return this.#messagesStream.messages.pipe( - filter(({ id }) => id === msg.id), - map((msg) => msg.payload as ResponsePayload), - ); - } -} diff --git a/apps/wallet/src/dapp-interface/index.ts b/apps/wallet/src/dapp-interface/index.ts deleted file mode 100644 index 32dcf3969d8e7..0000000000000 --- a/apps/wallet/src/dapp-interface/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { registerWallet } from '@mysten/wallet-standard'; - -import { SuiWallet } from './WalletStandardInterface'; - -registerWallet(new SuiWallet()); diff --git a/apps/wallet/src/dapp-interface/utils.ts b/apps/wallet/src/dapp-interface/utils.ts deleted file mode 100644 index 62e7a5c4d69e1..0000000000000 --- a/apps/wallet/src/dapp-interface/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isErrorPayload, type Payload } from '_payloads'; -import { lastValueFrom, map, take, type Observable } from 'rxjs'; - -export function mapToPromise( - stream: Observable, - project: (value: T) => R, -) { - return lastValueFrom( - stream.pipe( - take(1), - map((response) => { - if (response && isErrorPayload(response)) { - // TODO: throw proper error - throw new Error(response.message); - } - return project(response); - }), - ), - ); -} diff --git a/apps/wallet/src/manifest/icons/sui-icon-128.png b/apps/wallet/src/manifest/icons/sui-icon-128.png deleted file mode 100644 index c0a690f759a47..0000000000000 Binary files a/apps/wallet/src/manifest/icons/sui-icon-128.png and /dev/null differ diff --git a/apps/wallet/src/manifest/icons/sui-icon-16.png b/apps/wallet/src/manifest/icons/sui-icon-16.png deleted file mode 100644 index 96323855dc8aa..0000000000000 Binary files a/apps/wallet/src/manifest/icons/sui-icon-16.png and /dev/null differ diff --git a/apps/wallet/src/manifest/icons/sui-icon-32.png b/apps/wallet/src/manifest/icons/sui-icon-32.png deleted file mode 100644 index a6c79805b18ff..0000000000000 Binary files a/apps/wallet/src/manifest/icons/sui-icon-32.png and /dev/null differ diff --git a/apps/wallet/src/manifest/icons/sui-icon-48.png b/apps/wallet/src/manifest/icons/sui-icon-48.png deleted file mode 100644 index edf5bd97d775f..0000000000000 Binary files a/apps/wallet/src/manifest/icons/sui-icon-48.png and /dev/null differ diff --git a/apps/wallet/src/manifest/manifest.json b/apps/wallet/src/manifest/manifest.json deleted file mode 100644 index 4f05777b29d89..0000000000000 --- a/apps/wallet/src/manifest/manifest.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "AUTO_UPDATED", - "description": "AUTO_UPDATED", - "version": "AUTO_UPDATED", - "manifest_version": 3, - "background": { - "service_worker": "background.js" - }, - "permissions": ["storage", "tabs", "alarms", "unlimitedStorage", "identity"], - "action": { - "default_popup": "ui.html?type=popup" - }, - "host_permissions": [ - "http://127.0.0.1:5001/", - "https://fullnode.devnet.sui.io/", - "https://fullnode.staging.sui.io/" - ], - "icons": { - "16": "manifest/icons/sui-icon-16.png", - "32": "manifest/icons/sui-icon-32.png", - "48": "manifest/icons/sui-icon-48.png", - "128": "manifest/icons/sui-icon-128.png" - }, - "content_scripts": [ - { - "matches": [""], - "js": ["content-script.js"], - "run_at": "document_start" - } - ], - "web_accessible_resources": [ - { - "resources": ["dapp-interface.js"], - "matches": [""] - }, - { - "resources": ["ui.html"], - "matches": ["https://*.banxa.com/*"] - } - ], - "content_security_policy": { - "extension_pages": "default-src 'none'; object-src 'none'; connect-src *; font-src 'self'; img-src * data:; media-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'self'; form-action 'none'; frame-ancestors 'none';" - } -} diff --git a/apps/wallet/src/shared/analytics/ampli/index.ts b/apps/wallet/src/shared/analytics/ampli/index.ts deleted file mode 100644 index 03db6920b3800..0000000000000 --- a/apps/wallet/src/shared/analytics/ampli/index.ts +++ /dev/null @@ -1,1942 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -/* tslint:disable */ -/* eslint-disable */ -// @ts-nocheck -/** - * Ampli - A strong typed wrapper for your Analytics - * - * This file is generated by Amplitude. - * To update run 'ampli pull web' - * - * Required dependencies: @amplitude/analytics-browser@^1.3.0 - * Tracking Plan Version: 6 - * Build: 1.0.0 - * Runtime: browser:typescript-ampli-v2 - * - * [View Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest) - * - * [Full Setup Instructions](https://data.amplitude.com/mystenlabs/Sui%20Wallet/implementation/web) - */ - -import * as amplitude from '@amplitude/analytics-browser'; - -export type Environment = 'production' | 'development'; - -export const ApiKey: Record = { - production: '05c63856469c4e1d4aa9a6c1b2298d3b', - development: '938968357fcb3bf031d27b5049f62449', -}; - -/** - * Default Amplitude configuration options. Contains tracking plan information. - */ -export const DefaultConfiguration: BrowserOptions = { - plan: { - version: '6', - branch: 'main', - source: 'web', - versionId: '77fa44dc-250a-4e7e-8b74-164834834066', - }, - ...{ - ingestionMetadata: { - sourceName: 'browser-typescript-ampli', - sourceVersion: '2.0.0', - }, - }, -}; - -export interface LoadOptionsBase { - disabled?: boolean; -} - -export type LoadOptionsWithEnvironment = LoadOptionsBase & { - environment: Environment; - client?: { configuration?: BrowserOptions }; -}; -export type LoadOptionsWithApiKey = LoadOptionsBase & { - client: { apiKey: string; configuration?: BrowserOptions }; -}; -export type LoadOptionsWithClientInstance = LoadOptionsBase & { - client: { instance: BrowserClient }; -}; - -export type LoadOptions = - | LoadOptionsWithEnvironment - | LoadOptionsWithApiKey - | LoadOptionsWithClientInstance; - -export interface IdentifyProperties { - /** - * The type of account currently being used by the user. - */ - activeAccountType?: string; - /** - * The Sui Network that the user is currently interacting with. - */ - activeNetwork: string; - /** - * The active origin website that the extension is being used on. - */ - activeOrigin?: string; - /** - * The path (e.g., /apps) of a given screen in the wallet. - */ - pagePath: string; - /** - * The fully qualified path fragment (e.g., /apps?is_connected=true) of a given screen. - */ - pagePathFragment: string; - /** - * The mode that the wallet is currently in. - * - * | Rule | Value | - * |---|---| - * | Enum Values | Fullscreen, Pop-up | - */ - walletAppMode?: 'Fullscreen' | 'Pop-up'; - /** - * The version of the wallet the user has installed. - */ - walletVersion: string; -} - -export interface AddedAccountsProperties { - /** - * The type of wallet account (e.g., Ledger, Qredo, etc.) - * - * | Rule | Value | - * |---|---| - * | Enum Values | Ledger, Qredo, Derived, Imported, Zklogin | - */ - accountType: 'Ledger' | 'Qredo' | 'Derived' | 'Imported' | 'Zklogin'; - /** - * The number of accounts imported. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - numberOfAccounts: number; -} - -export interface BypassedScamWarningProperties { - hostname: string; -} - -export interface ClickedBullsharkQuestsCtaProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedCollectibleCardProperties { - /** - * The object type of a collectible. - */ - collectibleType: string; - /** - * | Rule | Value | - * |---|---| - * | Type | number | - */ - count?: number; - /** - * Whether or not a collectible card represents a Kiosk. - */ - isKiosk?: boolean; - /** - * The ID of an object on Sui. - */ - objectId: string; - sourceScreen?: string; -} - -export interface ClickedCreateNewAccountProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedHideAssetProperties { - /** - * The object type of a collectible. - */ - collectibleType: string; - /** - * The ID of an object on Sui. - */ - objectId: string; -} - -export interface ClickedImportPassphraseProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedImportPrivateKeyProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedSocialSignInButtonProperties { - /** - * The name (e.g., Microsoft) of a social sign-in provider. - * - * | Rule | Value | - * |---|---| - * | Enum Values | Microsoft, Facebook, Google, Twitch, Kakao, Apple | - */ - signInProvider: 'Microsoft' | 'Facebook' | 'Google' | 'Twitch' | 'Kakao' | 'Apple'; - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedStakeSuiProperties { - /** - * Whether or not the user is already staking some SUI. - */ - isCurrentlyStaking: boolean; - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface ClickedSwapCoinProperties { - /** - * The type of a coin. - */ - coinType: string; - /** - * The flow the user came from. - */ - sourceFlow: string; - /** - * The total balance of the selected coin that the user has. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - totalBalance?: number; -} - -export interface ClickedTokenClaimsBannerProperties { - /** - * A generic name property that can be used across events. - */ - name: string; - /** - * The ID of an object on Sui. - */ - objectId: string; - objectType: string; -} - -export interface ClickedUnstakeSuiProperties { - /** - * The amount of SUI staked. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - stakedAmount: number; - /** - * The address of the selected validator. - */ - validatorAddress: string; -} - -export interface ClickedUsdcPromoBannerProperties { - /** - * | Rule | Value | - * |---|---| - * | Item Type | string | - */ - wUsdcInAccount: string[]; -} - -export interface ConnectedHardwareWalletProperties { - /** - * The type of hardware wallet that was connected to. - * - * | Rule | Value | - * |---|---| - * | Enum Values | Ledger | - */ - hardwareWalletType: 'Ledger'; -} - -export interface CreatedNewWalletProperties { - /** - * Whether or not the keypair was imported during onboarding. - */ - imported?: boolean; - /** - * The type of account provider used during onboarding. - * - * | Rule | Value | - * |---|---| - * | Enum Values | mnemonic, keypair, zklogin | - */ - onboardingProvider: 'mnemonic' | 'keypair' | 'zklogin'; -} - -export interface DisconnectedApplicationProperties { - /** - * The name of the application being visited. - */ - applicationName?: string; - /** - * The URL of the application that was disconnected. - */ - applicationUrl: string; - /** - * The number of accounts that were disconnected. - * - * | Rule | Value | - * |---|---| - * | Type | integer | - */ - disconnectedAccounts: number; - /** - * The flow the user disconnected the application from. - */ - sourceFlow: string; -} - -export interface ImportedExistingAccountProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface InteractedWithMaliciousDomainProperties { - hostname: string; -} - -export interface OpenedApplicationProperties { - /** - * The name of the application being visited. - */ - applicationName: string; -} - -export interface OpenedConnectLedgerFlowProperties { - /** - * The flow the user came from. - */ - sourceFlow: string; -} - -export interface PinnedCoinProperties { - /** - * The type of a coin. - */ - coinType: string; -} - -export interface ReceivedOnrampProvidersDataProperties { - countryCode?: string; - /** - * | Rule | Value | - * |---|---| - * | Item Type | string | - */ - providerNames: string[]; - region?: string; -} - -export interface ReceivedOnrampProvidersDataFailedProperties { - countryCode: string; - /** - * A message associated with an error event. - */ - errorMessage: string; - region?: string; -} - -export interface RespondedToConnectionRequestProperties { - /** - * The name of the application that initiated the connection request. - */ - applicationName?: string; - /** - * The URL of the application that initiated the transaction. - */ - applicationUrl: string; - /** - * Whether or not the user approved an application connection request. - */ - approvedConnection: boolean; -} - -export interface RespondedToTransactionRequestProperties { - /** - * The URL of the application that initiated the transaction. - */ - applicationUrl: string; - /** - * Whether or not a transaction request was approved. - */ - approvedTransaction: boolean; - /** - * Whether or not users received a failure warning when signing a transaction. - */ - receivedFailureWarning: boolean; - /** - * | Rule | Value | - * |---|---| - * | Enum Values | sign, sign-and-execute | - */ - type: 'sign' | 'sign-and-execute'; -} - -export interface SelectedCoinProperties { - /** - * The type of a coin. - */ - coinType: string; - /** - * The flow the user came from. - */ - sourceFlow: string; - /** - * The total balance of the selected coin that the user has. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - totalBalance?: number; -} - -export interface SelectedValidatorProperties { - /** - * The address of the selected validator. - */ - validatorAddress: string; - /** - * The current APY % of the selected validator. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - validatorAPY: number; - /** - * The name of the selected validator. - */ - validatorName: string; -} - -export interface SentCoinFailedProperties { - /** - * A message associated with an error event. - */ - errorMessage: string; -} - -export interface SentCoinsProperties { - coinType: string; -} - -export interface SentCollectibleProperties { - /** - * The ID of an object on Sui. - */ - objectId: string; -} - -export interface SentCollectibleFailedProperties { - /** - * A message associated with an error event. - */ - errorMessage: string; - /** - * The ID of an object on Sui. - */ - objectId: string; -} - -export interface SignedTransactionBlockFailedProperties { - /** - * | Rule | Value | - * |---|---| - * | Enum Values | sign, signAndExecute | - */ - action: 'sign' | 'signAndExecute'; - /** - * A message associated with an error event. - */ - errorMessage: string; -} - -export interface StakedSuiProperties { - /** - * The amount of SUI staked. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - stakedAmount: number; - /** - * The address of the selected validator. - */ - validatorAddress: string; -} - -export interface StakedSuiFailedProperties { - /** - * A message associated with an error event. - */ - errorMessage: string; - /** - * The amount of SUI staked. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - stakedAmount: number; - /** - * The address of the selected validator. - */ - validatorAddress: string; -} - -export interface SwappedCoinProperties { - /** - * | Rule | Value | - * |---|---| - * | Type | number | - */ - estimatedReturnBalance: number; - fromCoinType: string; - /** - * swap provider name - */ - provider?: string; - toCoinType: string; - /** - * The total balance of the selected coin that the user has. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - totalBalance?: number; -} - -export interface SwappedCoinFailedProperties { - /** - * A message associated with an error event. - */ - errorMessage: string; - /** - * | Rule | Value | - * |---|---| - * | Type | number | - */ - estimatedReturnBalance: number; - fromCoinType: string; - /** - * swap provider name - */ - provider?: string; - toCoinType: string; - /** - * The total balance of the selected coin that the user has. - * - * | Rule | Value | - * |---|---| - * | Type | number | - */ - totalBalance?: number; -} - -export interface SwitchedAccountProperties { - /** - * The type of account that is being switched to. - */ - toAccountType: string; -} - -export interface SwitchedNetworkProperties { - toNetwork: string; -} - -export interface UnpinnedCoinProperties { - /** - * The type of a coin. - */ - coinType: string; -} - -export interface UnstakedSuiProperties { - /** - * The address of the selected validator. - */ - validatorAddress: string; -} - -export interface VisitedFiatOnRampProperties { - countryCode?: string; - isBestRate?: boolean; - /** - * The name of the fiat on-ramp provider. - */ - providerName: string; - region?: string; -} - -export class Identify implements BaseEvent { - event_type = amplitude.Types.SpecialEventType.IDENTIFY; - - constructor(public event_properties: IdentifyProperties) { - this.event_properties = event_properties; - } -} - -export class AddedAccounts implements BaseEvent { - event_type = 'added accounts'; - - constructor(public event_properties: AddedAccountsProperties) { - this.event_properties = event_properties; - } -} - -export class BypassedScamWarning implements BaseEvent { - event_type = 'bypassed scam warning'; - - constructor(public event_properties: BypassedScamWarningProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedBullsharkQuestsCta implements BaseEvent { - event_type = 'clicked bullshark quests cta'; - - constructor(public event_properties: ClickedBullsharkQuestsCtaProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedCollectibleCard implements BaseEvent { - event_type = 'clicked collectible card'; - - constructor(public event_properties: ClickedCollectibleCardProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedCreateNewAccount implements BaseEvent { - event_type = 'clicked create new account'; - - constructor(public event_properties: ClickedCreateNewAccountProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedCreateNewWallet implements BaseEvent { - event_type = 'clicked create new wallet'; -} - -export class ClickedGetStarted implements BaseEvent { - event_type = 'clicked get started'; -} - -export class ClickedHideAsset implements BaseEvent { - event_type = 'clicked hide asset'; - - constructor(public event_properties: ClickedHideAssetProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedImportExistingWallet implements BaseEvent { - event_type = 'clicked import existing wallet'; -} - -export class ClickedImportPassphrase implements BaseEvent { - event_type = 'clicked import passphrase'; - - constructor(public event_properties: ClickedImportPassphraseProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedImportPrivateKey implements BaseEvent { - event_type = 'clicked import private key'; - - constructor(public event_properties: ClickedImportPrivateKeyProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedSocialSignInButton implements BaseEvent { - event_type = 'clicked social sign in button'; - - constructor(public event_properties: ClickedSocialSignInButtonProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedStakeSui implements BaseEvent { - event_type = 'clicked stake SUI'; - - constructor(public event_properties: ClickedStakeSuiProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedSwapCoin implements BaseEvent { - event_type = 'clicked swap coin'; - - constructor(public event_properties: ClickedSwapCoinProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedTokenClaimsBanner implements BaseEvent { - event_type = 'clicked token claims banner'; - - constructor(public event_properties: ClickedTokenClaimsBannerProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedUnstakeSui implements BaseEvent { - event_type = 'clicked unstake SUI'; - - constructor(public event_properties: ClickedUnstakeSuiProperties) { - this.event_properties = event_properties; - } -} - -export class ClickedUsdcPromoBanner implements BaseEvent { - event_type = 'clicked usdc promo banner'; - - constructor(public event_properties: ClickedUsdcPromoBannerProperties) { - this.event_properties = event_properties; - } -} - -export class ConnectedHardwareWallet implements BaseEvent { - event_type = 'connected hardware wallet'; - - constructor(public event_properties: ConnectedHardwareWalletProperties) { - this.event_properties = event_properties; - } -} - -export class CreatedNewWallet implements BaseEvent { - event_type = 'created new wallet'; - - constructor(public event_properties: CreatedNewWalletProperties) { - this.event_properties = event_properties; - } -} - -export class DisconnectedApplication implements BaseEvent { - event_type = 'disconnected application'; - - constructor(public event_properties: DisconnectedApplicationProperties) { - this.event_properties = event_properties; - } -} - -export class ImportedExistingAccount implements BaseEvent { - event_type = 'imported existing account'; - - constructor(public event_properties: ImportedExistingAccountProperties) { - this.event_properties = event_properties; - } -} - -export class InteractedWithMaliciousDomain implements BaseEvent { - event_type = 'interacted with malicious domain'; - - constructor(public event_properties: InteractedWithMaliciousDomainProperties) { - this.event_properties = event_properties; - } -} - -export class OpenedApplication implements BaseEvent { - event_type = 'opened application'; - - constructor(public event_properties: OpenedApplicationProperties) { - this.event_properties = event_properties; - } -} - -export class OpenedConnectLedgerFlow implements BaseEvent { - event_type = 'opened connect ledger flow'; - - constructor(public event_properties: OpenedConnectLedgerFlowProperties) { - this.event_properties = event_properties; - } -} - -export class OpenedWalletExtension implements BaseEvent { - event_type = 'opened wallet extension'; -} - -export class PinnedCoin implements BaseEvent { - event_type = 'pinned coin'; - - constructor(public event_properties: PinnedCoinProperties) { - this.event_properties = event_properties; - } -} - -export class ReceivedOnrampProvidersData implements BaseEvent { - event_type = 'received onramp providers data'; - - constructor(public event_properties: ReceivedOnrampProvidersDataProperties) { - this.event_properties = event_properties; - } -} - -export class ReceivedOnrampProvidersDataFailed implements BaseEvent { - event_type = 'Received onramp providers data (failed)'; - - constructor(public event_properties: ReceivedOnrampProvidersDataFailedProperties) { - this.event_properties = event_properties; - } -} - -export class RespondedToConnectionRequest implements BaseEvent { - event_type = 'responded to connection request'; - - constructor(public event_properties: RespondedToConnectionRequestProperties) { - this.event_properties = event_properties; - } -} - -export class RespondedToTransactionRequest implements BaseEvent { - event_type = 'responded to transaction request'; - - constructor(public event_properties: RespondedToTransactionRequestProperties) { - this.event_properties = event_properties; - } -} - -export class SelectedCoin implements BaseEvent { - event_type = 'selected coin'; - - constructor(public event_properties: SelectedCoinProperties) { - this.event_properties = event_properties; - } -} - -export class SelectedValidator implements BaseEvent { - event_type = 'selected validator'; - - constructor(public event_properties: SelectedValidatorProperties) { - this.event_properties = event_properties; - } -} - -export class SentCoinFailed implements BaseEvent { - event_type = 'sent coin failed'; - - constructor(public event_properties: SentCoinFailedProperties) { - this.event_properties = event_properties; - } -} - -export class SentCoins implements BaseEvent { - event_type = 'sent coins'; - - constructor(public event_properties: SentCoinsProperties) { - this.event_properties = event_properties; - } -} - -export class SentCollectible implements BaseEvent { - event_type = 'sent collectible'; - - constructor(public event_properties: SentCollectibleProperties) { - this.event_properties = event_properties; - } -} - -export class SentCollectibleFailed implements BaseEvent { - event_type = 'sent collectible (failed)'; - - constructor(public event_properties: SentCollectibleFailedProperties) { - this.event_properties = event_properties; - } -} - -export class SignedTransactionBlockFailed implements BaseEvent { - event_type = 'signed transaction block failed'; - - constructor(public event_properties: SignedTransactionBlockFailedProperties) { - this.event_properties = event_properties; - } -} - -export class StakedSui implements BaseEvent { - event_type = 'staked SUI'; - - constructor(public event_properties: StakedSuiProperties) { - this.event_properties = event_properties; - } -} - -export class StakedSuiFailed implements BaseEvent { - event_type = 'staked SUI (failed)'; - - constructor(public event_properties: StakedSuiFailedProperties) { - this.event_properties = event_properties; - } -} - -export class SwappedCoin implements BaseEvent { - event_type = 'swapped coin'; - - constructor(public event_properties: SwappedCoinProperties) { - this.event_properties = event_properties; - } -} - -export class SwappedCoinFailed implements BaseEvent { - event_type = 'swapped coin (failed)'; - - constructor(public event_properties: SwappedCoinFailedProperties) { - this.event_properties = event_properties; - } -} - -export class SwitchedAccount implements BaseEvent { - event_type = 'switched account'; - - constructor(public event_properties: SwitchedAccountProperties) { - this.event_properties = event_properties; - } -} - -export class SwitchedNetwork implements BaseEvent { - event_type = 'switched network'; - - constructor(public event_properties: SwitchedNetworkProperties) { - this.event_properties = event_properties; - } -} - -export class UnpinnedCoin implements BaseEvent { - event_type = 'unpinned coin'; - - constructor(public event_properties: UnpinnedCoinProperties) { - this.event_properties = event_properties; - } -} - -export class UnstakedSui implements BaseEvent { - event_type = 'unstaked SUI'; - - constructor(public event_properties: UnstakedSuiProperties) { - this.event_properties = event_properties; - } -} - -export class ViewedLedgerTutorial implements BaseEvent { - event_type = 'viewed ledger tutorial'; -} - -export class VisitedFiatOnRamp implements BaseEvent { - event_type = 'visited fiat on-ramp'; - - constructor(public event_properties: VisitedFiatOnRampProperties) { - this.event_properties = event_properties; - } -} - -export type PromiseResult = { promise: Promise }; - -const getVoidPromiseResult = () => ({ promise: Promise.resolve() }); - -// prettier-ignore -export class Ampli { - private disabled: boolean = false; - private amplitude?: BrowserClient; - - get client(): BrowserClient { - this.isInitializedAndEnabled(); - return this.amplitude!; - } - - get isLoaded(): boolean { - return this.amplitude != null; - } - - private isInitializedAndEnabled(): boolean { - if (!this.amplitude) { - console.error('ERROR: Ampli is not yet initialized. Have you called ampli.load() on app start?'); - return false; - } - return !this.disabled; - } - - /** - * Initialize the Ampli SDK. Call once when your application starts. - * - * @param options Configuration options to initialize the Ampli SDK with. - */ - load(options: LoadOptions): PromiseResult { - this.disabled = options.disabled ?? false; - - if (this.amplitude) { - console.warn('WARNING: Ampli is already intialized. Ampli.load() should be called once at application startup.'); - return getVoidPromiseResult(); - } - - let apiKey: string | null = null; - if (options.client && 'apiKey' in options.client) { - apiKey = options.client.apiKey; - } else if ('environment' in options) { - apiKey = ApiKey[options.environment]; - } - - if (options.client && 'instance' in options.client) { - this.amplitude = options.client.instance; - } else if (apiKey) { - this.amplitude = amplitude.createInstance(); - const configuration = (options.client && 'configuration' in options.client) ? options.client.configuration : {}; - return this.amplitude.init(apiKey, undefined, { ...DefaultConfiguration, ...configuration }); - } else { - console.error("ERROR: ampli.load() requires 'environment', 'client.apiKey', or 'client.instance'"); - } - - return getVoidPromiseResult(); - } - - /** - * Identify a user and set user properties. - * - * @param userId The user's id. - * @param properties The user properties. - * @param options Optional event options. - */ - identify( - userId: string | undefined, - properties: IdentifyProperties, - options?: EventOptions, - ): PromiseResult { - if (!this.isInitializedAndEnabled()) { - return getVoidPromiseResult(); - } - - if (userId) { - options = {...options, user_id: userId}; - } - - const amplitudeIdentify = new amplitude.Identify(); - const eventProperties = properties; - if (eventProperties != null) { - for (const [key, value] of Object.entries(eventProperties)) { - amplitudeIdentify.set(key, value); - } - } - return this.amplitude!.identify( - amplitudeIdentify, - options, - ); - } - - /** - * Flush the event. - */ - flush() : PromiseResult { - if (!this.isInitializedAndEnabled()) { - return getVoidPromiseResult(); - } - - return this.amplitude!.flush(); - } - - /** - * Track event - * - * @param event The event to track. - * @param options Optional event options. - */ - track(event: Event, options?: EventOptions): PromiseResult { - if (!this.isInitializedAndEnabled()) { - return getVoidPromiseResult(); - } - - return this.amplitude!.track(event, undefined, options); - } - - /** - * added accounts - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/added%20accounts) - * - * When users successfully add new accounts to the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. accountType) - * @param options Amplitude event options. - */ - addedAccounts( - properties: AddedAccountsProperties, - options?: EventOptions, - ) { - return this.track(new AddedAccounts(properties), options); - } - - /** - * bypassed scam warning - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/bypassed%20scam%20warning) - * - * Event to track when users bypass a scam warning within the wallet - * - * @param properties The event's properties (e.g. hostname) - * @param options Amplitude event options. - */ - bypassedScamWarning( - properties: BypassedScamWarningProperties, - options?: EventOptions, - ) { - return this.track(new BypassedScamWarning(properties), options); - } - - /** - * clicked bullshark quests cta - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20bullshark%20quests%20cta) - * - * When users click the call-to-action for the interstitial/banner. - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - clickedBullsharkQuestsCta( - properties: ClickedBullsharkQuestsCtaProperties, - options?: EventOptions, - ) { - return this.track(new ClickedBullsharkQuestsCta(properties), options); - } - - /** - * clicked collectible card - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20collectible%20card) - * - * When users click to view a collectible in the wallet. - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. collectibleType) - * @param options Amplitude event options. - */ - clickedCollectibleCard( - properties: ClickedCollectibleCardProperties, - options?: EventOptions, - ) { - return this.track(new ClickedCollectibleCard(properties), options); - } - - /** - * clicked create new account - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20create%20new%20account) - * - * When users click the button to create a new passphrase account. - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - clickedCreateNewAccount( - properties: ClickedCreateNewAccountProperties, - options?: EventOptions, - ) { - return this.track(new ClickedCreateNewAccount(properties), options); - } - - /** - * clicked create new wallet - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20create%20new%20wallet) - * - * When users click to create a new wallet during onboarding. - * - * Owner: Jon Shek - * - * @param options Amplitude event options. - */ - clickedCreateNewWallet( - options?: EventOptions, - ) { - return this.track(new ClickedCreateNewWallet(), options); - } - - /** - * clicked get started - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20get%20started) - * - * When users click "Get Started" after installing the wallet. - * - * Owner: Jon Shek - * - * @param options Amplitude event options. - */ - clickedGetStarted( - options?: EventOptions, - ) { - return this.track(new ClickedGetStarted(), options); - } - - /** - * clicked hide asset - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20hide%20asset) - * - * Event has no description in tracking plan. - * - * @param properties The event's properties (e.g. collectibleType) - * @param options Amplitude event options. - */ - clickedHideAsset( - properties: ClickedHideAssetProperties, - options?: EventOptions, - ) { - return this.track(new ClickedHideAsset(properties), options); - } - - /** - * clicked import existing wallet - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20import%20existing%20wallet) - * - * When users click to import an existing wallet during onboarding. - * - * Owner: Jon Shek - * - * @param options Amplitude event options. - */ - clickedImportExistingWallet( - options?: EventOptions, - ) { - return this.track(new ClickedImportExistingWallet(), options); - } - - /** - * clicked import passphrase - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20import%20passphrase) - * - * When users click to import an account via passphrase. - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - clickedImportPassphrase( - properties: ClickedImportPassphraseProperties, - options?: EventOptions, - ) { - return this.track(new ClickedImportPassphrase(properties), options); - } - - /** - * clicked import private key - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20import%20private%20key) - * - * When users click the button to import an account via private key. - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - clickedImportPrivateKey( - properties: ClickedImportPrivateKeyProperties, - options?: EventOptions, - ) { - return this.track(new ClickedImportPrivateKey(properties), options); - } - - /** - * clicked social sign in button - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20social%20sign%20in%20button) - * - * When users click a social sign-in button to create an account. - * - * @param properties The event's properties (e.g. signInProvider) - * @param options Amplitude event options. - */ - clickedSocialSignInButton( - properties: ClickedSocialSignInButtonProperties, - options?: EventOptions, - ) { - return this.track(new ClickedSocialSignInButton(properties), options); - } - - /** - * clicked stake SUI - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20stake%20SUI) - * - * When users click to stake SUI in the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. isCurrentlyStaking) - * @param options Amplitude event options. - */ - clickedStakeSui( - properties: ClickedStakeSuiProperties, - options?: EventOptions, - ) { - return this.track(new ClickedStakeSui(properties), options); - } - - /** - * clicked swap coin - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20swap%20coin) - * - * When users click to swap a coin in the wallet - * - * @param properties The event's properties (e.g. coinType) - * @param options Amplitude event options. - */ - clickedSwapCoin( - properties: ClickedSwapCoinProperties, - options?: EventOptions, - ) { - return this.track(new ClickedSwapCoin(properties), options); - } - - /** - * clicked token claims banner - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20token%20claims%20banner) - * - * Event has no description in tracking plan. - * - * @param properties The event's properties (e.g. name) - * @param options Amplitude event options. - */ - clickedTokenClaimsBanner( - properties: ClickedTokenClaimsBannerProperties, - options?: EventOptions, - ) { - return this.track(new ClickedTokenClaimsBanner(properties), options); - } - - /** - * clicked unstake SUI - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20unstake%20SUI) - * - * When users click to unstake SUI. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. stakedAmount) - * @param options Amplitude event options. - */ - clickedUnstakeSui( - properties: ClickedUnstakeSuiProperties, - options?: EventOptions, - ) { - return this.track(new ClickedUnstakeSui(properties), options); - } - - /** - * clicked usdc promo banner - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/clicked%20usdc%20promo%20banner) - * - * Event has no description in tracking plan. - * - * @param properties The event's properties (e.g. wUsdcInAccount) - * @param options Amplitude event options. - */ - clickedUsdcPromoBanner( - properties: ClickedUsdcPromoBannerProperties, - options?: EventOptions, - ) { - return this.track(new ClickedUsdcPromoBanner(properties), options); - } - - /** - * connected hardware wallet - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/connected%20hardware%20wallet) - * - * When users successfully connect their hardware wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. hardwareWalletType) - * @param options Amplitude event options. - */ - connectedHardwareWallet( - properties: ConnectedHardwareWalletProperties, - options?: EventOptions, - ) { - return this.track(new ConnectedHardwareWallet(properties), options); - } - - /** - * created new wallet - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/created%20new%20wallet) - * - * When users successfully create a new wallet during onboarding. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. imported) - * @param options Amplitude event options. - */ - createdNewWallet( - properties: CreatedNewWalletProperties, - options?: EventOptions, - ) { - return this.track(new CreatedNewWallet(properties), options); - } - - /** - * disconnected application - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/disconnected%20application) - * - * When users disconnect from an application in the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. applicationName) - * @param options Amplitude event options. - */ - disconnectedApplication( - properties: DisconnectedApplicationProperties, - options?: EventOptions, - ) { - return this.track(new DisconnectedApplication(properties), options); - } - - /** - * imported existing account - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/imported%20existing%20account) - * - * When users successfully import an existing account during onboarding. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - importedExistingAccount( - properties: ImportedExistingAccountProperties, - options?: EventOptions, - ) { - return this.track(new ImportedExistingAccount(properties), options); - } - - /** - * interacted with malicious domain - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/interacted%20with%20malicious%20domain) - * - * Event to track when a user interacts with a malicious domain and is shown the malicious domain warning overlay. - * - * @param properties The event's properties (e.g. hostname) - * @param options Amplitude event options. - */ - interactedWithMaliciousDomain( - properties: InteractedWithMaliciousDomainProperties, - options?: EventOptions, - ) { - return this.track(new InteractedWithMaliciousDomain(properties), options); - } - - /** - * opened application - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/opened%20application) - * - * When users click to open an application from the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. applicationName) - * @param options Amplitude event options. - */ - openedApplication( - properties: OpenedApplicationProperties, - options?: EventOptions, - ) { - return this.track(new OpenedApplication(properties), options); - } - - /** - * opened connect ledger flow - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/opened%20connect%20ledger%20flow) - * - * When users open the "Connect Ledger Wallet" flow. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. sourceFlow) - * @param options Amplitude event options. - */ - openedConnectLedgerFlow( - properties: OpenedConnectLedgerFlowProperties, - options?: EventOptions, - ) { - return this.track(new OpenedConnectLedgerFlow(properties), options); - } - - /** - * opened wallet extension - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/opened%20wallet%20extension) - * - * When users first open the wallet extension. - * - * Owner: Jon Shek - * - * @param options Amplitude event options. - */ - openedWalletExtension( - options?: EventOptions, - ) { - return this.track(new OpenedWalletExtension(), options); - } - - /** - * pinned coin - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/pinned%20coin) - * - * When users pin an unrecognized coin on the home page. - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. coinType) - * @param options Amplitude event options. - */ - pinnedCoin( - properties: PinnedCoinProperties, - options?: EventOptions, - ) { - return this.track(new PinnedCoin(properties), options); - } - - /** - * received onramp providers data - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/received%20onramp%20providers%20data) - * - * Event to track when data from onramp providers is received - * - * @param properties The event's properties (e.g. countryCode) - * @param options Amplitude event options. - */ - receivedOnrampProvidersData( - properties: ReceivedOnrampProvidersDataProperties, - options?: EventOptions, - ) { - return this.track(new ReceivedOnrampProvidersData(properties), options); - } - - /** - * Received onramp providers data (failed) - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/Received%20onramp%20providers%20data%20(failed)) - * - * Event to track when data from onramp providers is received - * - * @param properties The event's properties (e.g. countryCode) - * @param options Amplitude event options. - */ - receivedOnrampProvidersDataFailed( - properties: ReceivedOnrampProvidersDataFailedProperties, - options?: EventOptions, - ) { - return this.track(new ReceivedOnrampProvidersDataFailed(properties), options); - } - - /** - * responded to connection request - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/responded%20to%20connection%20request) - * - * When users respond to a connection request in the wallet. - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. applicationName) - * @param options Amplitude event options. - */ - respondedToConnectionRequest( - properties: RespondedToConnectionRequestProperties, - options?: EventOptions, - ) { - return this.track(new RespondedToConnectionRequest(properties), options); - } - - /** - * responded to transaction request - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/responded%20to%20transaction%20request) - * - * When users respond to a transaction request from an application. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. applicationUrl) - * @param options Amplitude event options. - */ - respondedToTransactionRequest( - properties: RespondedToTransactionRequestProperties, - options?: EventOptions, - ) { - return this.track(new RespondedToTransactionRequest(properties), options); - } - - /** - * selected coin - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/selected%20coin) - * - * When users select a specific coin from the home screen. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. coinType) - * @param options Amplitude event options. - */ - selectedCoin( - properties: SelectedCoinProperties, - options?: EventOptions, - ) { - return this.track(new SelectedCoin(properties), options); - } - - /** - * selected validator - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/selected%20validator) - * - * When users select a validator in the staking flow. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. validatorAddress) - * @param options Amplitude event options. - */ - selectedValidator( - properties: SelectedValidatorProperties, - options?: EventOptions, - ) { - return this.track(new SelectedValidator(properties), options); - } - - /** - * sent coin failed - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/sent%20coin%20failed) - * - * Event to track errors encountered while sending coins - * - * @param properties The event's properties (e.g. errorMessage) - * @param options Amplitude event options. - */ - sentCoinFailed( - properties: SentCoinFailedProperties, - options?: EventOptions, - ) { - return this.track(new SentCoinFailed(properties), options); - } - - /** - * sent coins - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/sent%20coins) - * - * When users successfully send coins to someone. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. coinType) - * @param options Amplitude event options. - */ - sentCoins( - properties: SentCoinsProperties, - options?: EventOptions, - ) { - return this.track(new SentCoins(properties), options); - } - - /** - * sent collectible - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/sent%20collectible) - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. objectId) - * @param options Amplitude event options. - */ - sentCollectible( - properties: SentCollectibleProperties, - options?: EventOptions, - ) { - return this.track(new SentCollectible(properties), options); - } - - /** - * sent collectible (failed) - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/sent%20collectible%20(failed)) - * - * Event has no description in tracking plan. - * - * @param properties The event's properties (e.g. errorMessage) - * @param options Amplitude event options. - */ - sentCollectibleFailed( - properties: SentCollectibleFailedProperties, - options?: EventOptions, - ) { - return this.track(new SentCollectibleFailed(properties), options); - } - - /** - * signed transaction block failed - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/signed%20transaction%20block%20failed) - * - * Event to track errors encountered while signing a transaction block - * - * @param properties The event's properties (e.g. action) - * @param options Amplitude event options. - */ - signedTransactionBlockFailed( - properties: SignedTransactionBlockFailedProperties, - options?: EventOptions, - ) { - return this.track(new SignedTransactionBlockFailed(properties), options); - } - - /** - * staked SUI - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/staked%20SUI) - * - * When users successfully stake SUI with a validator. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. stakedAmount) - * @param options Amplitude event options. - */ - stakedSui( - properties: StakedSuiProperties, - options?: EventOptions, - ) { - return this.track(new StakedSui(properties), options); - } - - /** - * staked SUI (failed) - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/staked%20SUI%20(failed)) - * - * Event fired when a user attempt to native stake SUI results in a failure. - * - * @param properties The event's properties (e.g. errorMessage) - * @param options Amplitude event options. - */ - stakedSuiFailed( - properties: StakedSuiFailedProperties, - options?: EventOptions, - ) { - return this.track(new StakedSuiFailed(properties), options); - } - - /** - * swapped coin - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/swapped%20coin) - * - * When users complete swapping 1 coin to another - * - * @param properties The event's properties (e.g. estimatedReturnBalance) - * @param options Amplitude event options. - */ - swappedCoin( - properties: SwappedCoinProperties, - options?: EventOptions, - ) { - return this.track(new SwappedCoin(properties), options); - } - - /** - * swapped coin (failed) - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/swapped%20coin%20(failed)) - * - * Event has no description in tracking plan. - * - * @param properties The event's properties (e.g. errorMessage) - * @param options Amplitude event options. - */ - swappedCoinFailed( - properties: SwappedCoinFailedProperties, - options?: EventOptions, - ) { - return this.track(new SwappedCoinFailed(properties), options); - } - - /** - * switched account - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/switched%20account) - * - * When users switch their active account in the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. toAccountType) - * @param options Amplitude event options. - */ - switchedAccount( - properties: SwitchedAccountProperties, - options?: EventOptions, - ) { - return this.track(new SwitchedAccount(properties), options); - } - - /** - * switched network - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/switched%20network) - * - * When users switch between different network connections. - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. toNetwork) - * @param options Amplitude event options. - */ - switchedNetwork( - properties: SwitchedNetworkProperties, - options?: EventOptions, - ) { - return this.track(new SwitchedNetwork(properties), options); - } - - /** - * unpinned coin - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/unpinned%20coin) - * - * When users un-pin a recognized coin on the home page. - * - * Owner: William Robertson - * - * @param properties The event's properties (e.g. coinType) - * @param options Amplitude event options. - */ - unpinnedCoin( - properties: UnpinnedCoinProperties, - options?: EventOptions, - ) { - return this.track(new UnpinnedCoin(properties), options); - } - - /** - * unstaked SUI - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/unstaked%20SUI) - * - * When users successfully un-stake SUI. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. validatorAddress) - * @param options Amplitude event options. - */ - unstakedSui( - properties: UnstakedSuiProperties, - options?: EventOptions, - ) { - return this.track(new UnstakedSui(properties), options); - } - - /** - * viewed ledger tutorial - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/viewed%20ledger%20tutorial) - * - * When users click the link to get help with connecting their Ledger wallet. - * - * Owner: Jon Shek - * - * @param options Amplitude event options. - */ - viewedLedgerTutorial( - options?: EventOptions, - ) { - return this.track(new ViewedLedgerTutorial(), options); - } - - /** - * visited fiat on-ramp - * - * [View in Tracking Plan](https://data.amplitude.com/mystenlabs/Sui%20Wallet/events/main/latest/visited%20fiat%20on-ramp) - * - * When users visit a fiat on-ramp from the wallet. - * - * Owner: Jon Shek - * - * @param properties The event's properties (e.g. countryCode) - * @param options Amplitude event options. - */ - visitedFiatOnRamp( - properties: VisitedFiatOnRampProperties, - options?: EventOptions, - ) { - return this.track(new VisitedFiatOnRamp(properties), options); - } -} - -export const ampli = new Ampli(); - -// BASE TYPES -type BrowserOptions = amplitude.Types.BrowserOptions; - -export type BrowserClient = amplitude.Types.BrowserClient; -export type BaseEvent = amplitude.Types.BaseEvent; -export type IdentifyEvent = amplitude.Types.IdentifyEvent; -export type GroupEvent = amplitude.Types.GroupIdentifyEvent; -export type Event = amplitude.Types.Event; -export type EventOptions = amplitude.Types.EventOptions; -export type Result = amplitude.Types.Result; diff --git a/apps/wallet/src/shared/analytics/amplitude.ts b/apps/wallet/src/shared/analytics/amplitude.ts deleted file mode 100644 index d6715459d89d6..0000000000000 --- a/apps/wallet/src/shared/analytics/amplitude.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import * as amplitude from '@amplitude/analytics-browser'; -import { LogLevel, TransportType, type UserSession } from '@amplitude/analytics-types'; -import { PersistableStorage } from '@mysten/core'; - -import { ampli } from './ampli'; - -const IS_PROD_ENV = process.env.NODE_ENV === 'production'; - -export const persistableStorage = new PersistableStorage(); - -export async function initAmplitude() { - ampli.load({ - environment: IS_PROD_ENV ? 'production' : 'development', - // Flip this if you'd like to test Amplitude locally - disabled: !IS_PROD_ENV, - client: { - configuration: { - cookieStorage: persistableStorage, - logLevel: IS_PROD_ENV ? LogLevel.Warn : LogLevel.Debug, - }, - }, - }); - - window.addEventListener('pagehide', () => { - amplitude.setTransport(TransportType.SendBeacon); - amplitude.flush(); - }); -} - -export function getUrlWithDeviceId(url: URL) { - const amplitudeDeviceId = ampli.client.getDeviceId(); - if (amplitudeDeviceId) { - url.searchParams.append('deviceId', amplitudeDeviceId); - } - return url; -} diff --git a/apps/wallet/src/shared/api-env.ts b/apps/wallet/src/shared/api-env.ts deleted file mode 100644 index c0f6b5121cc00..0000000000000 --- a/apps/wallet/src/shared/api-env.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export enum API_ENV { - mainnet = 'mainnet', - devNet = 'devNet', - testNet = 'testNet', - local = 'local', - customRPC = 'customRPC', -} - -export const networkNames: Record = { - [API_ENV.local]: 'Local', - [API_ENV.testNet]: 'Testnet', - [API_ENV.devNet]: 'Devnet', - [API_ENV.mainnet]: 'Mainnet', - [API_ENV.customRPC]: 'Custom RPC', -}; - -export type NetworkEnvType = - | { env: Exclude; customRpcUrl: null } - | { env: API_ENV.customRPC; customRpcUrl: string }; - -export const ENV_TO_API: Record = { - [API_ENV.customRPC]: null, - [API_ENV.local]: process.env.API_ENDPOINT_LOCAL_FULLNODE || '', - [API_ENV.devNet]: process.env.API_ENDPOINT_DEV_NET_FULLNODE || '', - [API_ENV.testNet]: process.env.API_ENDPOINT_TEST_NET_FULLNODE || '', - [API_ENV.mainnet]: process.env.API_ENDPOINT_MAINNET_FULLNODE || '', -}; diff --git a/apps/wallet/src/shared/constants.ts b/apps/wallet/src/shared/constants.ts deleted file mode 100644 index 43f35c88de5f0..0000000000000 --- a/apps/wallet/src/shared/constants.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export const ToS_LINK = 'https://mystenlabs.com/legal#suiwallettermsofservice'; -export const PRIVACY_POLICY_LINK = 'https://mystenlabs.com/legal#privacypolicy'; -export const FAQ_LINK = 'https://docs.mystenlabs.com/faq'; -export const DISCORD_LINK = 'https://discord.com/channels/1102609826707673098/1102651685601550427'; - -// number of epochs before earning -// Staking Rewards Redeemable -export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE = 2; -export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS = 1; -export const MIN_NUMBER_SUI_TO_STAKE = 1; -export const DELEGATED_STAKES_QUERY_STALE_TIME = 10_000; -export const DELEGATED_STAKES_QUERY_REFETCH_INTERVAL = 30_000; diff --git a/apps/wallet/src/shared/cryptography/keystore.test.ts b/apps/wallet/src/shared/cryptography/keystore.test.ts deleted file mode 100644 index 9c203a8e06334..0000000000000 --- a/apps/wallet/src/shared/cryptography/keystore.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { describe, expect, it } from 'vitest'; - -import { decrypt, encrypt } from './keystore'; - -describe('keystore', () => { - it('encrypt and decrypt success', async () => { - const password = 'password'; - const plaintext = JSON.stringify('hello world'); - const ciphertext = await encrypt(password, plaintext); - const result = await decrypt(password, ciphertext); - expect(result).toBe(plaintext); - }); - - it('encrypt and decrypt failed with wrong password', async () => { - const password = 'password'; - const plaintext = JSON.stringify('hello world'); - const ciphertext = await encrypt(password, plaintext); - await expect(decrypt('random', ciphertext)).rejects.toThrow('Incorrect password'); - }); -}); diff --git a/apps/wallet/src/shared/cryptography/keystore.ts b/apps/wallet/src/shared/cryptography/keystore.ts deleted file mode 100644 index 4cdc6e5cf1ba3..0000000000000 --- a/apps/wallet/src/shared/cryptography/keystore.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - decrypt as metamaskDecrypt, - encrypt as metamaskEncrypt, -} from '@metamask/browser-passworder'; -import { randomBytes } from '@noble/hashes/utils'; - -// we use this password + a random one for each time we store the encrypted -// vault to session storage -const PASSWORD = - process.env.WALLET_KEYRING_PASSWORD || - '344c6f7d04a65c24f35f5c710b0e91e2f2e2f88c038562622d5602019b937bc2c2aa2821e65cc94775fe5acf2fee240d38f1abbbe00b0e6682646a4ce10e908e'; - -export type Serializable = - | string - | number - | boolean - | null - | { [index: string]: Serializable | undefined } - | Serializable[] - | (Iterable & { length: number }); - -export async function encrypt(password: string, secrets: Serializable): Promise { - return metamaskEncrypt(password, secrets); -} - -export async function decrypt( - password: string, - ciphertext: string, -): Promise { - return (await metamaskDecrypt(password, ciphertext)) as T; -} - -export function getRandomPassword() { - // eslint-disable-next-line no-restricted-globals - return Buffer.from(randomBytes(64)).toString('hex'); -} - -export function makeEphemeraPassword(rndPass: string) { - return `${PASSWORD}${rndPass}`; -} - -const obfuscationPassword = 'Qe2wZcFYG5eFdSefWb27shstk2eUnNI39'; - -export function obfuscate(value: Serializable) { - return encrypt(obfuscationPassword, value); -} - -export function deobfuscate(obfuscatedValue: string) { - return decrypt(obfuscationPassword, obfuscatedValue); -} diff --git a/apps/wallet/src/shared/deepBook/context.tsx b/apps/wallet/src/shared/deepBook/context.tsx deleted file mode 100644 index 3ba09a23defef..0000000000000 --- a/apps/wallet/src/shared/deepBook/context.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useDeepBookConfigs } from '_app/hooks/deepbook/useDeepBookConfigs'; -import { useActiveAccount } from '_app/hooks/useActiveAccount'; -import { DEFAULT_WALLET_FEE_ADDRESS, type Coins } from '_pages/swap/constants'; -import { FEATURES } from '_shared/experimentation/features'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { useGetOwnedObjects } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { DeepBookClient } from '@mysten/deepbook'; -import { createContext, useContext, useMemo, type ReactNode } from 'react'; - -type DeepBookContextProps = { - client: DeepBookClient; - accountCapId: string; - configs: { - pools: Record; - coinsMap: Record; - }; - walletFeeAddress: string; -}; - -const DeepBookContext = createContext(null); - -interface DeepBookContextProviderProps { - children: ReactNode; -} - -export function useDeepBookContext() { - const context = useContext(DeepBookContext); - if (!context) { - throw new Error('useDeepBookContext must be used within a DeepBookContextProvider'); - } - return context; -} - -export function DeepBookContextProvider({ children }: DeepBookContextProviderProps) { - const suiClient = useSuiClient(); - const activeAccount = useActiveAccount(); - const activeAccountAddress = activeAccount?.address; - - const configs = useDeepBookConfigs(); - const walletFeeAddress = useFeatureValue(FEATURES.WALLET_FEE_ADDRESS, DEFAULT_WALLET_FEE_ADDRESS); - - const { data } = useGetOwnedObjects( - activeAccountAddress, - { StructType: '0xdee9::custodian_v2::AccountCap' }, - 1, - ); - - const objectContent = data?.pages?.[0]?.data?.[0]?.data?.content; - const objectFields = objectContent?.dataType === 'moveObject' ? objectContent?.fields : null; - - const accountCapId = (objectFields as Record)?.owner as string; - - const deepBookClient = useMemo(() => { - return new DeepBookClient(suiClient, accountCapId); - }, [accountCapId, suiClient]); - - const contextValue = useMemo(() => { - return { - client: deepBookClient, - accountCapId, - configs, - walletFeeAddress, - }; - }, [accountCapId, configs, deepBookClient, walletFeeAddress]); - - return {children}; -} diff --git a/apps/wallet/src/shared/experimentation/features.ts b/apps/wallet/src/shared/experimentation/features.ts deleted file mode 100644 index 44168f162820a..0000000000000 --- a/apps/wallet/src/shared/experimentation/features.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV } from '_src/shared/api-env'; -import { GrowthBook } from '@growthbook/growthbook'; -import Browser from 'webextension-polyfill'; - -export const growthbook = new GrowthBook({ - // If you want to develop locally, you can set the API host to this: - // apiHost: 'http://localhost:3003', - apiHost: 'https://apps-backend.sui.io', - clientKey: process.env.NODE_ENV === 'development' ? 'development' : 'production', - enableDevMode: process.env.NODE_ENV === 'development', -}); - -/** - * This is a list of feature keys that are used in wallet - * https://docs.growthbook.io/app/features#feature-keys - */ -export enum FEATURES { - USE_LOCAL_TXN_SERIALIZER = 'use-local-txn-serializer', - WALLET_DAPPS = 'wallet-dapps', - WALLET_BALANCE_REFETCH_INTERVAL = 'wallet-balance-refetch-interval', - WALLET_ACTIVITY_REFETCH_INTERVAL = 'wallet-activity-refetch-interval', - WALLET_EFFECTS_ONLY_SHARED_TRANSACTION = 'wallet-effects-only-shared-transaction', - WALLET_QREDO = 'wallet-qredo', - WALLET_APPS_BANNER_CONFIG = 'wallet-apps-banner-config', - WALLET_INTERSTITIAL_CONFIG = 'wallet-interstitial-config', - WALLET_DEFI = 'wallet-defi', - WALLET_FEE_ADDRESS = 'wallet-fee-address', - DEEP_BOOK_CONFIGS = 'deep-book-configs', - TOKEN_METADATA_OVERRIDES = 'token-metadata-overrides', -} - -export function setAttributes(network?: { apiEnv: API_ENV; customRPC?: string | null }) { - const activeNetwork = network - ? network.apiEnv === API_ENV.customRPC && network.customRPC - ? network.customRPC - : network.apiEnv.toUpperCase() - : null; - - growthbook.setAttributes({ - network: activeNetwork, - version: Browser.runtime.getManifest().version, - beta: process.env.WALLET_BETA || false, - }); -} - -// Initialize growthbook to default attributes: -setAttributes(); diff --git a/apps/wallet/src/shared/messaging/PortChannelName.ts b/apps/wallet/src/shared/messaging/PortChannelName.ts deleted file mode 100644 index 8a4ef89354a11..0000000000000 --- a/apps/wallet/src/shared/messaging/PortChannelName.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export type PortChannelName = 'sui_content<->background' | 'sui_ui<->background'; diff --git a/apps/wallet/src/shared/messaging/PortStream.ts b/apps/wallet/src/shared/messaging/PortStream.ts deleted file mode 100644 index ff0eacef3bbe9..0000000000000 --- a/apps/wallet/src/shared/messaging/PortStream.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { filter, fromEventPattern, map, share, take, takeUntil, tap } from 'rxjs'; -import type { Observable } from 'rxjs'; -import Browser from 'webextension-polyfill'; -import type { Runtime } from 'webextension-polyfill'; - -import type { Message } from './messages'; -import { isErrorPayload } from './messages/payloads'; -import type { PortChannelName } from './PortChannelName'; - -export class PortStream { - private _messagesStream: Observable; - private _disconnectStream: Observable; - private _port: Runtime.Port; - private _connected: boolean; - - public static connectToBackgroundService(name: PortChannelName): PortStream { - return new PortStream(Browser.runtime.connect({ name })); - } - - constructor(port: Runtime.Port) { - this._port = port; - this._disconnectStream = fromEventPattern( - (h) => this._port.onDisconnect.addListener(h), - (h) => this._port.onDisconnect.removeListener(h), - ).pipe( - take(1), - tap(() => (this._connected = false)), - share(), - ); - this._messagesStream = fromEventPattern( - (h) => this._port.onMessage.addListener(h), - (h) => this._port.onMessage.removeListener(h), - (msg) => msg, - ).pipe(share(), takeUntil(this._disconnectStream)); - this._connected = true; - } - - public get onMessage(): Observable { - return this._messagesStream; - } - - public get onDisconnect(): Observable { - return this._disconnectStream; - } - - public get connected(): boolean { - return this._connected; - } - - public sendMessage(msg: Message): Observable { - if (!this._port) { - throw new Error('Port to background service worker is not defined'); - } - this._port.postMessage(msg); - return this.createResponseObservable(msg.id); - } - - private createResponseObservable(requestMsgID: string): Observable { - return this._messagesStream.pipe( - filter((msg) => msg.id === requestMsgID), - map((msg) => { - if (isErrorPayload(msg.payload)) { - throw new Error(msg.payload.message); - } - return msg; - }), - ); - } -} diff --git a/apps/wallet/src/shared/messaging/WindowMessageStream.ts b/apps/wallet/src/shared/messaging/WindowMessageStream.ts deleted file mode 100644 index 59de5e1b1e771..0000000000000 --- a/apps/wallet/src/shared/messaging/WindowMessageStream.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Message } from '_messages'; -import { filter, fromEvent, map, share } from 'rxjs'; -import type { Observable } from 'rxjs'; - -export type ClientType = 'sui_in-page' | 'sui_content-script'; - -type WindowMessage = { - target: ClientType; - payload: Message; -}; - -export class WindowMessageStream { - public readonly messages: Observable; - private _name: ClientType; - private _target: ClientType; - - constructor(name: ClientType, target: ClientType) { - if (name === target) { - throw new Error('[WindowMessageStream] name and target must be different'); - } - this._name = name; - this._target = target; - this.messages = fromEvent>(window, 'message').pipe( - filter((message) => message.source === window && message.data.target === this._name), - map((message) => message.data.payload), - share(), - ); - } - - public send(payload: Message) { - const msg: WindowMessage = { - target: this._target, - payload, - }; - window.postMessage(msg); - } -} diff --git a/apps/wallet/src/shared/messaging/messages/Message.ts b/apps/wallet/src/shared/messaging/messages/Message.ts deleted file mode 100644 index 699833948fc03..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/Message.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { v4 as uuidV4 } from 'uuid'; - -import type { Payload } from './payloads/Payload'; - -export type Message = { - id: string; - payload: Payload; -}; - -export function createMessage( - payload: MsgPayload, - id?: string, -): Message { - return { - id: id || uuidV4(), - payload, - }; -} diff --git a/apps/wallet/src/shared/messaging/messages/index.ts b/apps/wallet/src/shared/messaging/messages/index.ts deleted file mode 100644 index c497e2d300457..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './Message'; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/BasePayload.ts b/apps/wallet/src/shared/messaging/messages/payloads/BasePayload.ts deleted file mode 100644 index aee37b789326e..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/BasePayload.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Payload } from './Payload'; - -export type PayloadType = - | 'permission-request' - | 'permission-response' - | 'get-permission-requests' - | 'get-account' - | 'get-account-response' - | 'has-permissions-request' - | 'has-permissions-response' - | 'acquire-permissions-request' - | 'acquire-permissions-response' - | 'execute-transaction-request' - | 'execute-transaction-response' - | 'sign-transaction-request' - | 'sign-transaction-response' - | 'get-transaction-requests' - | 'get-transaction-requests-response' - | 'transaction-request-response' - | 'update-active-origin' - | 'disconnect-app' - | 'done' - | 'keyring' - | 'wallet-status-changed' - | 'get-features' - | 'features-response' - | 'get-network' - | 'set-network' - | 'sign-message-request' - | 'qredo-connect' - | 'method-payload'; - -export interface BasePayload { - type: PayloadType; -} - -export function isBasePayload(payload: Payload): payload is BasePayload { - return 'type' in payload && typeof payload.type !== 'undefined'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/ErrorPayload.ts b/apps/wallet/src/shared/messaging/messages/payloads/ErrorPayload.ts deleted file mode 100644 index 0939069fccdef..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/ErrorPayload.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Payload } from './Payload'; - -export interface ErrorPayload { - error: true; - code: number; - message: string; -} - -export function isErrorPayload(payload: Payload): payload is ErrorPayload { - return 'error' in payload && payload.error === true; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts b/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts deleted file mode 100644 index f2aeaeb1b29d9..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -/* eslint-disable @typescript-eslint/ban-types */ - -import { type AccountSourceSerializedUI } from '_src/background/account-sources/AccountSource'; -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { type ZkLoginProvider } from '_src/background/accounts/zklogin/providers'; -import { type Status } from '_src/background/legacy-accounts/storage-migration'; - -import { isBasePayload } from './BasePayload'; -import type { Payload } from './Payload'; - -export type UIAccessibleEntityType = 'accountSources' | 'accounts'; -export type LedgerAccountsPublicKeys = { - accountID: string; - publicKey: string; -}[]; -export type PasswordRecoveryData = { type: 'mnemonic'; accountSourceID: string; entropy: string }; - -type MethodPayloads = { - getStoredEntities: { type: UIAccessibleEntityType }; - storedEntitiesResponse: { entities: any; type: UIAccessibleEntityType }; - createAccountSource: { - type: 'mnemonic'; - params: { - password: string; - entropy?: string; - }; - }; - accountSourceCreationResponse: { accountSource: AccountSourceSerializedUI }; - lockAccountSourceOrAccount: { id: string }; - unlockAccountSourceOrAccount: { id: string; password?: string }; - createAccounts: - | { type: 'mnemonic-derived'; sourceID: string } - | { type: 'imported'; keyPair: string; password: string } - | { - type: 'ledger'; - accounts: { publicKey: string; derivationPath: string; address: string }[]; - password: string; - } - | { - type: 'zkLogin'; - provider: ZkLoginProvider; - }; - accountsCreatedResponse: { accounts: SerializedUIAccount[] }; - signData: { data: string; id: string }; - signDataResponse: { signature: string }; - entitiesUpdated: { type: UIAccessibleEntityType }; - getStorageMigrationStatus: null; - storageMigrationStatus: { status: Status }; - doStorageMigration: { password: string }; - switchAccount: { accountID: string }; - setAccountNickname: { id: string; nickname: string | null }; - verifyPassword: { password: string; legacyAccounts?: boolean }; - storeLedgerAccountsPublicKeys: { publicKeysToStore: LedgerAccountsPublicKeys }; - getAccountSourceEntropy: { accountSourceID: string; password?: string }; - getAccountSourceEntropyResponse: { entropy: string }; - clearWallet: {}; - getAutoLockMinutes: {}; - getAutoLockMinutesResponse: { minutes: number | null }; - setAutoLockMinutes: { minutes: number | null }; - notifyUserActive: {}; - getAccountKeyPair: { accountID: string; password: string }; - getAccountKeyPairResponse: { accountID: string; keyPair: string }; - resetPassword: { - password: string; - recoveryData: PasswordRecoveryData[]; - }; - verifyPasswordRecoveryData: { - data: PasswordRecoveryData; - }; - removeAccount: { accountID: string }; - acknowledgeZkLoginWarning: { accountID: string }; -}; - -type Methods = keyof MethodPayloads; - -export interface MethodPayload { - type: 'method-payload'; - method: M; - args: MethodPayloads[M]; -} - -export function isMethodPayload( - payload: Payload, - method: M, -): payload is MethodPayload { - return ( - isBasePayload(payload) && - payload.type === 'method-payload' && - 'method' in payload && - payload.method === method && - 'args' in payload - ); -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/Payload.ts b/apps/wallet/src/shared/messaging/messages/payloads/Payload.ts deleted file mode 100644 index 74f24999396a8..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/Payload.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { BasePayload } from './BasePayload'; -import type { ErrorPayload } from './ErrorPayload'; - -export type Payload = BasePayload | ErrorPayload; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/QredoConnect.ts b/apps/wallet/src/shared/messaging/messages/payloads/QredoConnect.ts deleted file mode 100644 index d8c5eb1cfa620..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/QredoConnect.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type QredoSerializedUiAccount } from '_src/background/accounts/QredoAccount'; -import { type UIQredoInfo, type UIQredoPendingRequest } from '_src/background/qredo/types'; -import { type QredoConnectInput } from '_src/dapp-interface/WalletStandardInterface'; -import { type Wallet } from '_src/shared/qredo-api'; - -import { isBasePayload, type BasePayload } from './BasePayload'; -import { type Payload } from './Payload'; - -type Methods = { - connect: QredoConnectInput; - connectResponse: { allowed: boolean }; - getPendingRequest: { requestID: string }; - getPendingRequestResponse: { request: UIQredoPendingRequest | null }; - getQredoInfo: { - qredoID: string; - refreshAccessToken: boolean; - }; - getQredoInfoResponse: { qredoInfo: UIQredoInfo | null }; - acceptQredoConnection: { - qredoID: string; - accounts: Wallet[]; - password: string; - }; - acceptQredoConnectionResponse: { accounts: QredoSerializedUiAccount[] }; - rejectQredoConnection: { - qredoID: string; - }; -}; - -export interface QredoConnectPayload extends BasePayload { - type: 'qredo-connect'; - method: M; - args: Methods[M]; -} - -export function isQredoConnectPayload( - payload: Payload, - method: M, -): payload is QredoConnectPayload { - return ( - isBasePayload(payload) && - payload.type === 'qredo-connect' && - 'method' in payload && - payload.method === method && - 'args' in payload && - !!payload.args - ); -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccount.ts b/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccount.ts deleted file mode 100644 index 73698252ec3b5..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccount.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface GetAccount extends BasePayload { - type: 'get-account'; -} - -export function isGetAccount(payload: Payload): payload is GetAccount { - return isBasePayload(payload) && payload.type === 'get-account'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccountResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccountResponse.ts deleted file mode 100644 index c27944196b824..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/account/GetAccountResponse.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { BasePayload } from '_payloads'; - -export interface GetAccountResponse extends BasePayload { - type: 'get-account-response'; - accounts: { address: string; publicKey: string | null; nickname: string | null }[]; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/feature-gating/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/feature-gating/index.ts deleted file mode 100644 index 7983961ee0ec7..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/feature-gating/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import type { GrowthBook } from '@growthbook/growthbook'; - -export type LoadedFeatures = Parameters['0']; -export type LoadedAttributes = Parameters['0']; - -export interface LoadedFeaturesPayload extends BasePayload { - type: 'features-response'; - features: LoadedFeatures; - attributes: LoadedAttributes; -} - -export function isLoadedFeaturesPayload(payload: Payload): payload is LoadedFeaturesPayload { - return isBasePayload(payload) && payload.type === 'features-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/index.ts deleted file mode 100644 index e9e0aded426b2..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './BasePayload'; -export * from './ErrorPayload'; -export * from './Payload'; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/network/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/network/index.ts deleted file mode 100644 index a51a710eba733..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/network/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import type { NetworkEnvType } from '_src/shared/api-env'; - -export interface SetNetworkPayload extends BasePayload { - type: 'set-network'; - network: NetworkEnvType; -} - -export function isSetNetworkPayload(payload: Payload): payload is SetNetworkPayload { - return isBasePayload(payload) && payload.type === 'set-network'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsRequest.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsRequest.ts deleted file mode 100644 index f073a1e4a68ad..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsRequest.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -import type { PermissionType } from './PermissionType'; - -export interface AcquirePermissionsRequest extends BasePayload { - type: 'acquire-permissions-request'; - permissions: readonly PermissionType[]; -} - -export function isAcquirePermissionsRequest( - payload: Payload, -): payload is AcquirePermissionsRequest { - return isBasePayload(payload) && payload.type === 'acquire-permissions-request'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsResponse.ts deleted file mode 100644 index b15c4f7e10b8c..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/AcquirePermissionsResponse.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface AcquirePermissionsResponse extends BasePayload { - type: 'acquire-permissions-response'; - result: boolean; -} - -export function isAcquirePermissionsResponse( - payload: Payload, -): payload is AcquirePermissionsResponse { - return isBasePayload(payload) && payload.type === 'acquire-permissions-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/DisconnectApp.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/DisconnectApp.ts deleted file mode 100644 index ac43ae18e3bcc..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/DisconnectApp.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface DisconnectApp extends BasePayload { - type: 'disconnect-app'; - origin: string; - specificAccounts?: string[]; -} - -export function isDisconnectApp(payload: Payload): payload is DisconnectApp { - return isBasePayload(payload) && payload.type === 'disconnect-app'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/GetPermissionRequests.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/GetPermissionRequests.ts deleted file mode 100644 index de5e391000ea9..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/GetPermissionRequests.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface GetPermissionRequests extends BasePayload { - type: 'get-permission-requests'; -} - -export function isGetPermissionRequests(payload: Payload): payload is GetPermissionRequests { - return isBasePayload(payload) && payload.type === 'get-permission-requests'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsRequest.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsRequest.ts deleted file mode 100644 index 3a83f41970d26..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsRequest.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -import type { PermissionType } from './PermissionType'; - -export interface HasPermissionsRequest extends BasePayload { - type: 'has-permissions-request'; - permissions: readonly PermissionType[]; -} - -export function isHasPermissionRequest(payload: Payload): payload is HasPermissionsRequest { - return isBasePayload(payload) && payload.type === 'has-permissions-request'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsResponse.ts deleted file mode 100644 index b78c26184a910..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/HasPermissionsResponse.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface HasPermissionsResponse extends BasePayload { - type: 'has-permissions-response'; - result: boolean; -} - -export function isHasPermissionResponse(payload: Payload): payload is HasPermissionsResponse { - return isBasePayload(payload) && payload.type === 'has-permissions-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/Permission.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/Permission.ts deleted file mode 100644 index cc0d4e7e3eadb..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/Permission.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { PermissionType } from './PermissionType'; - -//TODO: add description, name, tags -//TODO add PageLink for instance where the origin and the wallet landing page are different. -export interface Permission { - name?: string; - id: string; - origin: string; - pagelink?: string | undefined; - favIcon: string | undefined; - accounts: string[]; - allowed: boolean | null; - permissions: PermissionType[]; - createdDate: string; - responseDate: string | null; - requestMsgID: string; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionRequests.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionRequests.ts deleted file mode 100644 index 64faebda61daa..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionRequests.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -import type { Permission } from './Permission'; - -export interface PermissionRequests extends BasePayload { - type: 'permission-request'; - permissions: Permission[]; -} - -export function isPermissionRequests(payload: Payload): payload is PermissionRequests { - return isBasePayload(payload) && payload.type === 'permission-request'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionResponse.ts deleted file mode 100644 index adadf06ec9a37..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionResponse.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface PermissionResponse extends BasePayload { - type: 'permission-response'; - id: string; - accounts: string[]; - allowed: boolean; - responseDate: string; -} - -export function isPermissionResponse(payload: Payload): payload is PermissionResponse { - return isBasePayload(payload) && payload.type === 'permission-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionType.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionType.ts deleted file mode 100644 index 0bcf9dcddc664..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/PermissionType.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export const ALL_PERMISSION_TYPES = ['viewAccount', 'suggestTransactions'] as const; -type AllPermissionsType = typeof ALL_PERMISSION_TYPES; -export type PermissionType = AllPermissionsType[number]; - -/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ -export function isValidPermissionTypes(types: any): types is PermissionType[] { - return ( - Array.isArray(types) && - !!types.length && - types.every((aType) => ALL_PERMISSION_TYPES.includes(aType)) - ); -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/permissions/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/permissions/index.ts deleted file mode 100644 index 9b919481bf719..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/permissions/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './GetPermissionRequests'; -export * from './PermissionRequests'; -export * from './PermissionResponse'; -export * from './PermissionType'; -export * from './Permission'; -export * from './HasPermissionsRequest'; -export * from './HasPermissionsResponse'; -export * from './AcquirePermissionsRequest'; -export * from './AcquirePermissionsResponse'; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/tabs/updateActiveOrigin.ts b/apps/wallet/src/shared/messaging/messages/payloads/tabs/updateActiveOrigin.ts deleted file mode 100644 index 9e0eca40200ea..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/tabs/updateActiveOrigin.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface UpdateActiveOrigin extends BasePayload { - type: 'update-active-origin'; - origin: string | null; - favIcon: string | null; -} - -export function isUpdateActiveOrigin(payload: Payload): payload is UpdateActiveOrigin { - return isBasePayload(payload) && payload.type === 'update-active-origin'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts deleted file mode 100644 index 588b0a69b61ad..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { - type SuiSignAndExecuteTransactionBlockInput, - type SuiSignMessageOutput, -} from '@mysten/wallet-standard'; - -export type TransactionDataType = { - type: 'transaction'; - data: string; - account: string; - justSign?: boolean; - requestType?: SuiSignAndExecuteTransactionBlockInput['requestType']; - options?: SuiSignAndExecuteTransactionBlockInput['options']; -}; - -export type SignMessageDataType = { - type: 'sign-message'; - message: string; - accountAddress: string; -}; - -export type ApprovalRequest = { - id: string; - approved: boolean | null; - origin: string; - originFavIcon?: string; - txResult?: SuiTransactionBlockResponse | SuiSignMessageOutput; - txResultError?: string; - txSigned?: SignedTransaction; - createdDate: string; - tx: TransactionDataType | SignMessageDataType; -}; - -export interface SignMessageApprovalRequest extends Omit { - tx: SignMessageDataType; - txResult?: SuiSignMessageOutput; -} - -export interface TransactionApprovalRequest extends Omit { - tx: TransactionDataType; - txResult?: SuiTransactionBlockResponse; -} - -export function isSignMessageApprovalRequest( - request: ApprovalRequest, -): request is SignMessageApprovalRequest { - return request.tx.type === 'sign-message'; -} - -export function isTransactionApprovalRequest( - request: ApprovalRequest, -): request is TransactionApprovalRequest { - return request.tx.type !== 'sign-message'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionRequest.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionRequest.ts deleted file mode 100644 index ce9c4a9ba1608..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionRequest.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import { type SuiSignTransactionBlockInput } from '@mysten/wallet-standard'; - -import { type TransactionDataType } from './ApprovalRequest'; - -export interface ExecuteTransactionRequest extends BasePayload { - type: 'execute-transaction-request'; - transaction: TransactionDataType; -} - -export function isExecuteTransactionRequest( - payload: Payload, -): payload is ExecuteTransactionRequest { - return isBasePayload(payload) && payload.type === 'execute-transaction-request'; -} - -export type SuiSignTransactionSerialized = Omit< - SuiSignTransactionBlockInput, - 'transactionBlock' | 'account' -> & { - transaction: string; - account: string; -}; - -export interface SignTransactionRequest extends BasePayload { - type: 'sign-transaction-request'; - transaction: SuiSignTransactionSerialized; -} - -export function isSignTransactionRequest(payload: Payload): payload is SignTransactionRequest { - return isBasePayload(payload) && payload.type === 'sign-transaction-request'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts deleted file mode 100644 index 7681c5bbe5462..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { type SuiSignTransactionBlockOutput } from '@mysten/wallet-standard'; - -export interface ExecuteTransactionResponse extends BasePayload { - type: 'execute-transaction-response'; - result: SuiTransactionBlockResponse; -} - -export function isExecuteTransactionResponse( - payload: Payload, -): payload is ExecuteTransactionResponse { - return isBasePayload(payload) && payload.type === 'execute-transaction-response'; -} - -export interface SignTransactionResponse extends BasePayload { - type: 'sign-transaction-response'; - result: SuiSignTransactionBlockOutput; -} - -export function isSignTransactionResponse(payload: Payload): payload is SignTransactionResponse { - return isBasePayload(payload) && payload.type === 'sign-transaction-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/SignMessage.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/SignMessage.ts deleted file mode 100644 index 1239fb23f72b8..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/SignMessage.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SuiSignMessageOutput } from '@mysten/wallet-standard'; - -import { isBasePayload, type BasePayload } from '../BasePayload'; -import { type Payload } from '../Payload'; - -export interface SignMessageRequest extends BasePayload { - type: 'sign-message-request'; - args?: { - message: string; // base64 - accountAddress: string; - }; - return?: SuiSignMessageOutput; -} - -export function isSignMessageRequest(payload: Payload): payload is SignMessageRequest { - return isBasePayload(payload) && payload.type === 'sign-message-request'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/index.ts deleted file mode 100644 index 29211e1ae0e1a..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './ExecuteTransactionRequest'; -export * from './ExecuteTransactionResponse'; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequests.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequests.ts deleted file mode 100644 index d559d5bb69f2b..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequests.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; - -export interface GetTransactionRequests extends BasePayload { - type: 'get-transaction-requests'; -} - -export function isGetTransactionRequests(payload: Payload): payload is GetTransactionRequests { - return isBasePayload(payload) && payload.type === 'get-transaction-requests'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequestsResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequestsResponse.ts deleted file mode 100644 index 4fdf3001a7985..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/GetTransactionRequestsResponse.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import type { ApprovalRequest } from '_payloads/transactions/ApprovalRequest'; - -export interface GetTransactionRequestsResponse extends BasePayload { - type: 'get-transaction-requests-response'; - txRequests: ApprovalRequest[]; -} - -export function isGetTransactionRequestsResponse( - payload: Payload, -): payload is GetTransactionRequestsResponse { - return isBasePayload(payload) && payload.type === 'get-transaction-requests-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts deleted file mode 100644 index 94aa701f19b6c..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { type SuiSignMessageOutput } from '@mysten/wallet-standard'; - -export interface TransactionRequestResponse extends BasePayload { - type: 'transaction-request-response'; - txID: string; - approved: boolean; - txResult?: SuiTransactionBlockResponse | SuiSignMessageOutput; - txResultError?: string; - txSigned?: SignedTransaction; -} - -export function isTransactionRequestResponse( - payload: Payload, -): payload is TransactionRequestResponse { - return isBasePayload(payload) && payload.type === 'transaction-request-response'; -} diff --git a/apps/wallet/src/shared/messaging/messages/payloads/wallet-status-change/index.ts b/apps/wallet/src/shared/messaging/messages/payloads/wallet-status-change/index.ts deleted file mode 100644 index 42cd2b1de67b2..0000000000000 --- a/apps/wallet/src/shared/messaging/messages/payloads/wallet-status-change/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { isBasePayload } from '_payloads'; -import type { BasePayload, Payload } from '_payloads'; -import type { NetworkEnvType } from '_src/shared/api-env'; - -export type WalletStatusChange = { - network?: NetworkEnvType; - accounts?: { address: string; publicKey: string | null; nickname: string | null }[]; -}; - -export interface WalletStatusChangePayload extends BasePayload, WalletStatusChange { - type: 'wallet-status-changed'; -} - -export function isWalletStatusChangePayload( - payload: Payload, -): payload is WalletStatusChangePayload { - return isBasePayload(payload) && payload.type === 'wallet-status-changed'; -} diff --git a/apps/wallet/src/shared/qredo-api.ts b/apps/wallet/src/shared/qredo-api.ts deleted file mode 100644 index 24f2116f0afec..0000000000000 --- a/apps/wallet/src/shared/qredo-api.ts +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { toSearchQueryString } from './utils'; - -export type QredoAPIErrorResponse = { - code: string; - msg: string; - detail: { - reason: string; - }; -}; - -export class QredoAPIError extends Error { - status: number; - apiData: QredoAPIErrorResponse; - - constructor(status: number, apiData: QredoAPIErrorResponse) { - super(`Qredo API Error (status: ${status}). ${apiData.msg}`); - this.status = status; - this.apiData = apiData; - } -} - -export class QredoAPIUnauthorizedError extends QredoAPIError {} - -export type AccessTokenParams = { - refreshToken: string; - grantType?: string; -}; - -export type AccessTokenResponse = { - access_token: string; - expires_in: number; - token_type: string; -}; - -export type Wallet = { - walletID: string; - readonly address: string; - network: string; - // the key schema is always ED25519 and qredo is not planning to change it - publicKey: string; - labels: { - key: string; - name: string; - value: string; - }[]; -}; - -export type GetWalletsResponse = { - wallets: Wallet[]; -}; - -export type GetWalletsParams = { - filters?: { address?: string }; -}; - -export type NetworkType = 'mainnet' | 'testnet' | 'devnet'; - -export type TransactionStatus = - | 'pending' - | 'created' - | 'authorized' - | 'approved' - | 'expired' - | 'cancelled' - | 'rejected' - | 'signed' - | 'scheduled' - | 'pushed' - | 'confirmed' - | 'mined' - | 'failed'; - -export type PostTransactionParams = { - messageWithIntent: string; - broadcast: boolean; - network: NetworkType; - from: string; -}; - -export type TransactionInfoResponse = { - txID: string; - txHash: string; - status: TransactionStatus; - MessageWithIntent: string; - sig: string; - timestamps: Partial>; - events: { - id: string; - timestamp: number; - status: TransactionStatus; - message: string; - }[]; - from: string; - network: string; - createdBy: string; - accountID: string; -}; - -export type GetTransactionsParams = { - network?: NetworkType; - /** Filter by address or part of address */ - address?: string; - /** Qredo wallet id */ - wallet?: string; -}; - -export type GetTransactionsItem = { - walletID: string; - txID: string; - txHash: string; - status: TransactionStatus; -}; - -export type GetTransactionsResponse = { - list: GetTransactionsItem[]; -}; - -export type AccessTokenRenewalFunction = (qredoID: string) => Promise; - -const MAX_TRIES_TO_RENEW_ACCESS_TOKEN = 1; - -export class QredoAPI { - readonly baseURL: string; - readonly qredoID: string; - #accessToken: string | null; - #renewAccessTokenFN: AccessTokenRenewalFunction | null; - #accessTokenRenewInProgress: ReturnType | null = null; - - constructor( - qredoID: string, - baseURL: string, - options: { - accessToken?: string; - accessTokenRenewalFN?: AccessTokenRenewalFunction; - } = {}, - ) { - this.qredoID = qredoID; - this.baseURL = baseURL + (baseURL.endsWith('/') ? '' : '/'); - this.#accessToken = options.accessToken || null; - this.#renewAccessTokenFN = options.accessTokenRenewalFN || null; - } - - public set accessToken(accessToken: string) { - this.#accessToken = accessToken; - } - - public get accessToken() { - return this.#accessToken || ''; - } - - public createAccessToken({ - refreshToken, - grantType = 'refresh_token', - }: AccessTokenParams): Promise { - const params = new FormData(); - params.append('refresh_token', refreshToken); - if (grantType) { - params.append('grant_type', grantType); - } - return this.#request(`${this.baseURL}token`, { - method: 'post', - body: params, - }); - } - - public getWallets({ filters }: GetWalletsParams = {}): Promise { - const searchParams = new URLSearchParams(); - if (filters?.address) { - searchParams.append('address', filters.address); - } - return this.#request(`${this.baseURL}wallets${toSearchQueryString(searchParams)}`); - } - - public createTransaction(params: PostTransactionParams): Promise { - return this.#request(`${this.baseURL}transactions`, { - method: 'post', - body: JSON.stringify(params), - headers: { - 'Content-Type': 'application/json', - }, - }); - } - - public getTransaction(transactionID: string): Promise { - return this.#request(`${this.baseURL}transactions/${transactionID}`); - } - - public getTransactions(params: GetTransactionsParams): Promise { - return this.#request( - `${this.baseURL}transactions${toSearchQueryString(new URLSearchParams(params))}`, - ); - } - - async #renewAccessToken() { - if (!this.#renewAccessTokenFN) { - return false; - } - if (!this.#accessTokenRenewInProgress) { - this.#accessTokenRenewInProgress = this.#renewAccessTokenFN(this.qredoID).finally( - () => (this.#accessTokenRenewInProgress = null), - ); - } - this.#accessToken = await this.#accessTokenRenewInProgress; - return !!this.#accessToken; - } - - #request = async (...params: Parameters) => { - let tries = 0; - while (tries++ <= MAX_TRIES_TO_RENEW_ACCESS_TOKEN) { - // TODO: add monitoring? - const response = await fetch(params[0], { - ...params[1], - headers: { - ...params[1]?.headers, - Authorization: `Bearer ${this.#accessToken}`, - }, - }); - const dataJson = await response.json(); - if (response.ok) { - return dataJson; - } - if (response.status === 401 && tries <= MAX_TRIES_TO_RENEW_ACCESS_TOKEN) { - if (await this.#renewAccessToken()) { - // skip the rest and retry the request with the new access token - continue; - } - throw new QredoAPIUnauthorizedError(response.status, dataJson); - } - throw new QredoAPIError(response.status, dataJson); - } - }; -} diff --git a/apps/wallet/src/shared/sentry-config.ts b/apps/wallet/src/shared/sentry-config.ts deleted file mode 100644 index 66b3239d97f41..0000000000000 --- a/apps/wallet/src/shared/sentry-config.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type BrowserOptions } from '@sentry/browser'; -import Browser from 'webextension-polyfill'; - -const WALLET_VERSION = Browser.runtime.getManifest().version; -const IS_PROD = process.env.NODE_ENV === 'production'; - -// NOTE: If you want to enable sentry in dev, you can tweak this value: -const ENABLE_SENTRY = IS_PROD; - -const SENTRY_DSN = IS_PROD - ? 'https://e52a4e5c90224fe0800cc96aa2570581@o1314142.ingest.sentry.io/6761112' - : 'https://d1022411f6284cab9660146f3aa514d2@o1314142.ingest.sentry.io/4504697974751232'; - -export function getSentryConfig({ - integrations, - tracesSampler, -}: Pick): BrowserOptions { - return { - enabled: ENABLE_SENTRY, - dsn: SENTRY_DSN, - integrations, - release: WALLET_VERSION, - sampleRate: 0.05, - tracesSampler: IS_PROD ? tracesSampler : () => 1, - allowUrls: IS_PROD - ? [ - 'ehndjpedolgphielnhnpnkomdhgpaaei', // chrome beta - 'opcgpfmipidbgpenhmajoajpbobppdil', // chrome prod - ] - : undefined, - }; -} diff --git a/apps/wallet/src/shared/sui-client.ts b/apps/wallet/src/shared/sui-client.ts deleted file mode 100644 index 50fe95b12f2b0..0000000000000 --- a/apps/wallet/src/shared/sui-client.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import networkEnv from '_src/background/NetworkEnv'; -import { API_ENV, ENV_TO_API, type NetworkEnvType } from '_src/shared/api-env'; -import { SentryHttpTransport } from '@mysten/core'; -import { SuiClient, SuiHTTPTransport } from '@mysten/sui/client'; - -const suiClientPerNetwork = new Map(); -const SENTRY_MONITORED_ENVS = [API_ENV.mainnet]; - -export function getSuiClient({ env, customRpcUrl }: NetworkEnvType): SuiClient { - const key = `${env}_${customRpcUrl}`; - if (!suiClientPerNetwork.has(key)) { - const connection = customRpcUrl ? customRpcUrl : ENV_TO_API[env]; - if (!connection) { - throw new Error(`API url not found for network env ${env} ${customRpcUrl}`); - } - suiClientPerNetwork.set( - key, - new SuiClient({ - transport: - !customRpcUrl && SENTRY_MONITORED_ENVS.includes(env) - ? new SentryHttpTransport(connection) - : new SuiHTTPTransport({ url: connection }), - }), - ); - } - return suiClientPerNetwork.get(key)!; -} - -export async function getActiveNetworkSuiClient(): Promise { - return getSuiClient(await networkEnv.getActiveNetwork()); -} diff --git a/apps/wallet/src/shared/utils/bip39.test.ts b/apps/wallet/src/shared/utils/bip39.test.ts deleted file mode 100644 index 08850a4a3106d..0000000000000 --- a/apps/wallet/src/shared/utils/bip39.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { describe, expect, it } from 'vitest'; - -import { normalizeMnemonics, validateMnemonics } from './bip39'; - -describe('mnemonics', () => { - it('normalize mnemonics', () => { - expect(normalizeMnemonics(' Almost a Seed Phrase')).toEqual('almost a seed phrase'); - }); - - it('validate mnemonics', () => { - // Mnemonics length too short - expect(validateMnemonics('result')).toBe(false); - - // Invalid word not from the wordlist - expect( - validateMnemonics( - 'aaa crisp session latin must fruit genuine question prevent start coconut brave speak student dismiss', - ), - ).toBe(false); - - // Invalid checksum - expect( - validateMnemonics( - 'sleep kitten sleep kitten sleep kitten sleep kitten sleep kitten sleep kitten', - ), - ).toBe(false); - - // Test cases generated from https://iancoleman.io/bip39/ and https://github.com/trezor/python-mnemonic/blob/master/vectors.json - // Valid mnemonics 12 words - expect( - validateMnemonics( - 'result crisp session latin must fruit genuine question prevent start coconut brave speak student dismiss', - ), - ).toBeTruthy(); - - // Valid mnemonics 15 words - expect( - validateMnemonics( - 'slender myth trap industry peanut arrange depart guess chef common steel rookie brick enroll napkin', - ), - ).toBeTruthy(); - - // Valid mnemonics 18 words - expect( - validateMnemonics( - 'scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump', - ), - ).toBeTruthy(); - - // Valid mnemonics 21 words - expect( - validateMnemonics( - 'entry spoon private ridge clean salon loan surround apology fluid damage orbit embark digital polar find lazy bean plate burger august', - ), - ).toBeTruthy(); - - // Valid mnemonics 24 words - expect( - validateMnemonics( - 'void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold', - ), - ).toBeTruthy(); - - // Mnemonics length too long - expect( - validateMnemonics( - 'abandon void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold', - ), - ).toBe(false); - }); -}); diff --git a/apps/wallet/src/shared/utils/bip39.ts b/apps/wallet/src/shared/utils/bip39.ts deleted file mode 100644 index 6915b248e5d35..0000000000000 --- a/apps/wallet/src/shared/utils/bip39.ts +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { bytesToHex, hexToBytes, randomBytes } from '@noble/hashes/utils'; -import * as bip39 from '@scure/bip39'; -import { wordlist } from '@scure/bip39/wordlists/english'; - -/** - * Generate mnemonics as 12 words string using the english wordlist. - * - * @returns a 12 words string separated by spaces. - */ -export function generateMnemonic(): string { - return bip39.generateMnemonic(wordlist); -} - -/** - * Converts mnemonic to entropy (byte array) using the english wordlist. - * - * @param mnemonic 12-24 words - * - * @return the entropy of the mnemonic (Uint8Array) - */ -export function mnemonicToEntropy(mnemonic: string): Uint8Array { - return bip39.mnemonicToEntropy(mnemonic, wordlist); -} - -/** - * Converts entropy (byte array) to mnemonic using the english wordlist. - * - * @param entropy Uint8Array - * - * @return the mnemonic as string - */ -export function entropyToMnemonic(entropy: Uint8Array): string { - return bip39.entropyToMnemonic(entropy, wordlist); -} - -/** - * Generate random byte to be used as entropy for the mnemonic - * @param strength defaults to 128 to generate 12-word mnemonic that now is the default for the wallet - * @returns - */ -export function getRandomEntropy(strength: 128 | 256 = 128) { - return randomBytes(strength / 8); -} - -/** - * Validates entropy see https://github.com/paulmillr/scure-bip39/blob/4b4a17f13862da0b7ff3db1ef9d1bb3c2fc05e14/src/index.ts#L27 - * @param entropy - * @returns {boolean} true - * @throws if entropy is invalid - */ -export function validateEntropy(entropy: Uint8Array) { - assertBytes(entropy, 16, 20, 24, 28, 32); - return true; -} - -/** - * Validate a mnemonic string in the BIP39 English wordlist. - * - * @param mnemonics a words string split by spaces of length 12/15/18/21/24. - * - * @returns true if the mnemonic is valid, false otherwise. - */ -export function validateMnemonics(mnemonics: string): boolean { - return bip39.validateMnemonic(mnemonics, wordlist); -} - -/** - * Sanitize the mnemonics string provided by user. - * - * @param mnemonics a 12-word string split by spaces that may contain mixed cases - * and extra spaces. - * - * @returns a sanitized mnemonics string. - */ -export function normalizeMnemonics(mnemonics: string): string { - return mnemonics - .trim() - .split(/\s+/) - .map((part) => part.toLowerCase()) - .join(' '); -} - -/** - * Serializes entropy - * @param entropy - * @returns {string} the serialized value - */ -export function entropyToSerialized(entropy: Uint8Array) { - return bytesToHex(entropy); -} - -/** - * - * @param serializedEntropy the serialized value of entropy (produced by {@link entropyToSerialized}) - * @returns the entropy bytes - */ -export function toEntropy(serializedEntropy: string) { - return hexToBytes(serializedEntropy); -} - -// ported from https://github.com/paulmillr/noble-hashes/blob/main/src/_assert.ts#L9 -export function assertBytes(b: Uint8Array | undefined, ...lengths: number[]) { - if (!(b instanceof Uint8Array)) throw new TypeError('Expected Uint8Array'); - if (lengths.length > 0 && !lengths.includes(b.length)) - throw new TypeError(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`); -} diff --git a/apps/wallet/src/shared/utils/from-exported-keypair.ts b/apps/wallet/src/shared/utils/from-exported-keypair.ts deleted file mode 100644 index bdd5db37827e5..0000000000000 --- a/apps/wallet/src/shared/utils/from-exported-keypair.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - decodeSuiPrivateKey, - LEGACY_PRIVATE_KEY_SIZE, - PRIVATE_KEY_SIZE, - type Keypair, - type SignatureScheme, -} from '@mysten/sui/cryptography'; -import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; -import { Secp256k1Keypair } from '@mysten/sui/keypairs/secp256k1'; -import { Secp256r1Keypair } from '@mysten/sui/keypairs/secp256r1'; -import { fromBase64 } from '@mysten/sui/utils'; - -/** - * Wallet stored data might contain imported accounts with their keys stored in the previous format. - * Using this type to type-check it. - */ -export type LegacyExportedKeyPair = { - schema: SignatureScheme; - privateKey: string; -}; - -export function fromExportedKeypair( - secret: LegacyExportedKeyPair | string, - legacySupport = false, -): Keypair { - let schema; - let secretKey; - if (typeof secret === 'object') { - if (!legacySupport) { - throw new Error('Invalid type of secret key. A string value was expected.'); - } - secretKey = fromBase64(secret.privateKey); - schema = secret.schema; - } else { - const decoded = decodeSuiPrivateKey(secret); - schema = decoded.schema; - secretKey = decoded.secretKey; - } - switch (schema) { - case 'ED25519': - let pureSecretKey = secretKey; - if (secretKey.length === LEGACY_PRIVATE_KEY_SIZE) { - // This is a legacy secret key, we need to strip the public key bytes and only read the first 32 bytes - pureSecretKey = secretKey.slice(0, PRIVATE_KEY_SIZE); - } - return Ed25519Keypair.fromSecretKey(pureSecretKey); - case 'Secp256k1': - return Secp256k1Keypair.fromSecretKey(secretKey); - case 'Secp256r1': - return Secp256r1Keypair.fromSecretKey(secretKey); - default: - throw new Error(`Invalid keypair schema ${schema}`); - } -} diff --git a/apps/wallet/src/shared/utils/index.ts b/apps/wallet/src/shared/utils/index.ts deleted file mode 100644 index c982ed4e9ae0a..0000000000000 --- a/apps/wallet/src/shared/utils/index.ts +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useAppSelector } from '_hooks'; -import { setAttributes } from '_src/shared/experimentation/features'; -import { useGrowthBook } from '@growthbook/growthbook-react'; -import { fromBase64, toBase64 } from '@mysten/sui/utils'; -import * as Sentry from '@sentry/browser'; -import { useEffect } from 'react'; -import Browser from 'webextension-polyfill'; - -import { getUrlWithDeviceId } from '../analytics/amplitude'; - -export const MAIN_UI_URL = Browser.runtime.getURL('ui.html'); - -const MYSTEN_LABS_DAPPS = ['suifrens.com', 'suins.io']; - -export function openInNewTab() { - return Browser.tabs.create({ url: MAIN_UI_URL }); -} - -export function useSetGrowthbookAttributes() { - const { apiEnv, customRPC } = useAppSelector((state) => state.app); - const growthBook = useGrowthBook(); - - useEffect(() => { - if (growthBook) { - setAttributes({ apiEnv, customRPC }); - } - }, [growthBook, apiEnv, customRPC]); -} - -export function isValidUrl(url: string | null) { - if (!url) { - return false; - } - try { - new URL(url); - return true; - } catch (e) { - return false; - } -} - -export function getDAppUrl(appUrl: string) { - const url = new URL(appUrl); - const isMystenLabsDApp = MYSTEN_LABS_DAPPS.includes(url.hostname); - return isMystenLabsDApp ? getUrlWithDeviceId(url) : url; -} - -export function getValidDAppUrl(appUrl: string) { - try { - return getDAppUrl(appUrl); - } catch (error) { - /* empty */ - } - return null; -} - -export function prepareLinkToCompare(link: string) { - let adjLink = link.toLowerCase(); - if (!adjLink.endsWith('/')) { - adjLink += '/'; - } - return adjLink; -} - -/** - * Includes ? when query string is set - */ -export function toSearchQueryString(searchParams: URLSearchParams) { - const searchQuery = searchParams.toString(); - if (searchQuery) { - return `?${searchQuery}`; - } - return ''; -} - -export function toUtf8OrB64(message: string | Uint8Array) { - const messageBytes = typeof message === 'string' ? fromBase64(message) : message; - let messageToReturn: string = typeof message === 'string' ? message : toBase64(message); - let type: 'utf8' | 'base64' = 'base64'; - try { - messageToReturn = new TextDecoder('utf8', { fatal: true }).decode(messageBytes); - type = 'utf8'; - } catch (e) { - // do nothing - } - return { - message: messageToReturn, - type, - }; -} - -export async function fetchWithSentry(name: string, ...params: Parameters) { - const url = params[0] instanceof URL ? params[0].href : String(params[0]); - const transaction = Sentry.startTransaction({ - name, - op: 'http.request', - tags: { - url, - }, - }); - try { - const response = await fetch(...params); - if (!response.ok) { - throw new Error(`Request failed with status ${response.status} (${response.statusText})`); - } - transaction.setStatus('ok' as Sentry.SpanStatusType); - return response; - } catch (e) { - transaction.setStatus('unknown_error' as Sentry.SpanStatusType); - throw e; - } finally { - transaction.finish(); - } -} diff --git a/apps/wallet/src/shared/validation.ts b/apps/wallet/src/shared/validation.ts deleted file mode 100644 index a4e0e796a39d3..0000000000000 --- a/apps/wallet/src/shared/validation.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { formatBalance } from '@mysten/core'; -import BigNumber from 'bignumber.js'; -import * as Yup from 'yup'; - -export function createTokenValidation(coinBalance: bigint, coinSymbol: string, decimals: number) { - return Yup.mixed() - .transform((_, original) => { - return new BigNumber(original); - }) - .test('required', `\${path} is a required field`, (value) => { - return !!value; - }) - .test('valid', 'The value provided is not valid.', (value) => { - if (!value || value.isNaN() || !value.isFinite()) { - return false; - } - return true; - }) - .test('min', `\${path} must be greater than 0 ${coinSymbol}`, (amount) => - amount ? amount.gt(0) : false, - ) - .test( - 'max', - `\${path} must be less than ${formatBalance(coinBalance, decimals)} ${coinSymbol}`, - (amount) => (amount ? amount.shiftedBy(decimals).lte(coinBalance.toString()) : false), - ) - .test('max-decimals', `The value exceeds the maximum decimals (${decimals}).`, (amount) => { - return amount ? amount.shiftedBy(decimals).isInteger() : false; - }) - .label('Amount'); -} diff --git a/apps/wallet/src/types/assets.d.ts b/apps/wallet/src/types/assets.d.ts deleted file mode 100644 index 3e9a0bd6d039d..0000000000000 --- a/apps/wallet/src/types/assets.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -declare module '*.png' { - const src: string; - export default src; -} - -declare module '*.jpg' { - const src: string; - export default src; -} - -declare module '*.jpeg' { - const src: string; - export default src; -} - -declare module '*.gif' { - const src: string; - export default src; -} - -declare module '*.svg' { - import { type FC, type ComponentProps } from 'react'; - const component: FC>; - export default component; -} diff --git a/apps/wallet/src/types/css.d.ts b/apps/wallet/src/types/css.d.ts deleted file mode 100644 index 3c60c0cb9450b..0000000000000 --- a/apps/wallet/src/types/css.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -declare module '*.css' { - const css: string; - export default css; -} diff --git a/apps/wallet/src/types/node-env.d.ts b/apps/wallet/src/types/node-env.d.ts deleted file mode 100644 index 922989433f655..0000000000000 --- a/apps/wallet/src/types/node-env.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -declare namespace NodeJS { - interface ProcessEnv { - readonly NODE_ENV: 'development' | 'production' | 'test' | undefined; - } -} diff --git a/apps/wallet/src/types/scss-modules.d.ts b/apps/wallet/src/types/scss-modules.d.ts deleted file mode 100644 index eec59cdc84cb9..0000000000000 --- a/apps/wallet/src/types/scss-modules.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -declare module '*.module.scss' { - const classes: { readonly [key: string]: string }; - export default classes; -} diff --git a/apps/wallet/src/types/webextension-polyfill.d.ts b/apps/wallet/src/types/webextension-polyfill.d.ts deleted file mode 100644 index d0391375be9cb..0000000000000 --- a/apps/wallet/src/types/webextension-polyfill.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import type { Runtime } from 'webextension-polyfill'; - -declare module 'webextension-polyfill' { - declare namespace Runtime { - declare interface MessageSender { - // Chrome API has origin since v80 https://developer.chrome.com/docs/extensions/reference/runtime/#type-MessageSender - // Not sure why it's not in the polyfill - origin?: string; - } - } -} diff --git a/apps/wallet/src/ui/app/ApiProvider.ts b/apps/wallet/src/ui/app/ApiProvider.ts deleted file mode 100644 index 0b1fc004b3217..0000000000000 --- a/apps/wallet/src/ui/app/ApiProvider.ts +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type AccountType, type SerializedUIAccount } from '_src/background/accounts/Account'; -import { API_ENV } from '_src/shared/api-env'; -import { getSuiClient } from '_src/shared/sui-client'; -import { type SuiClient } from '@mysten/sui/client'; - -import type { BackgroundClient } from './background-client'; -import { BackgroundServiceSigner } from './background-client/BackgroundServiceSigner'; -import { queryClient } from './helpers/queryClient'; -import { type WalletSigner } from './WalletSigner'; - -type EnvInfo = { - name: string; - env: API_ENV; -}; - -export const API_ENV_TO_INFO: Record = { - [API_ENV.local]: { name: 'Local', env: API_ENV.local }, - [API_ENV.devNet]: { name: 'Devnet', env: API_ENV.devNet }, - [API_ENV.customRPC]: { name: 'Custom RPC', env: API_ENV.customRPC }, - [API_ENV.testNet]: { name: 'Testnet', env: API_ENV.testNet }, - [API_ENV.mainnet]: { name: 'Mainnet', env: API_ENV.mainnet }, -}; - -function getDefaultApiEnv() { - const apiEnv = process.env.API_ENV; - if (apiEnv && !Object.keys(API_ENV).includes(apiEnv)) { - throw new Error(`Unknown environment variable API_ENV, ${apiEnv}`); - } - return apiEnv ? API_ENV[apiEnv as keyof typeof API_ENV] : API_ENV.devNet; -} - -export const DEFAULT_API_ENV = getDefaultApiEnv(); - -type NetworkTypes = keyof typeof API_ENV; - -export const generateActiveNetworkList = (): NetworkTypes[] => { - return Object.values(API_ENV); -}; - -const accountTypesWithBackgroundSigner: AccountType[] = ['mnemonic-derived', 'imported', 'zkLogin']; - -export default class ApiProvider { - private _apiFullNodeProvider?: SuiClient; - private _signerByAddress: Map = new Map(); - apiEnv: API_ENV = DEFAULT_API_ENV; - - public setNewJsonRpcProvider(apiEnv: API_ENV = DEFAULT_API_ENV, customRPC?: string | null) { - this.apiEnv = apiEnv; - this._apiFullNodeProvider = getSuiClient( - apiEnv === API_ENV.customRPC - ? { env: apiEnv, customRpcUrl: customRPC || '' } - : { env: apiEnv, customRpcUrl: null }, - ); - - this._signerByAddress.clear(); - - // We also clear the query client whenever set set a new API provider: - queryClient.resetQueries(); - queryClient.clear(); - } - - public get instance() { - if (!this._apiFullNodeProvider) { - this.setNewJsonRpcProvider(); - } - return { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - fullNode: this._apiFullNodeProvider!, - }; - } - - public getSignerInstance( - account: SerializedUIAccount, - backgroundClient: BackgroundClient, - ): WalletSigner { - if (!this._apiFullNodeProvider) { - this.setNewJsonRpcProvider(); - } - if (accountTypesWithBackgroundSigner.includes(account.type)) { - return this.getBackgroundSignerInstance(account, backgroundClient); - } - if ('ledger' === account.type) { - // Ideally, Ledger transactions would be signed in the background - // and exist as an asynchronous keypair; however, this isn't possible - // because you can't connect to a Ledger device from the background - // script. Similarly, the signer instance can't be retrieved from - // here because ApiProvider is a global and results in very buggy - // behavior due to the reactive nature of managing Ledger connections - // and displaying relevant UI updates. Refactoring ApiProvider to - // not be a global instance would help out here, but that is also - // a non-trivial task because we need access to ApiProvider in the - // background script as well. - throw new Error("Signing with Ledger via ApiProvider isn't supported"); - } - throw new Error('Encountered unknown account type'); - } - - public getBackgroundSignerInstance( - account: SerializedUIAccount, - backgroundClient: BackgroundClient, - ): WalletSigner { - const key = account.id; - if (!this._signerByAddress.has(account.id)) { - this._signerByAddress.set( - key, - new BackgroundServiceSigner(account, backgroundClient, this._apiFullNodeProvider!), - ); - } - return this._signerByAddress.get(key)!; - } -} - -export const walletApiProvider = new ApiProvider(); diff --git a/apps/wallet/src/ui/app/LedgerSigner.ts b/apps/wallet/src/ui/app/LedgerSigner.ts deleted file mode 100644 index 02fd9886f7749..0000000000000 --- a/apps/wallet/src/ui/app/LedgerSigner.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type SuiLedgerClient from '@mysten/ledgerjs-hw-app-sui'; -import { type SuiClient } from '@mysten/sui/client'; -import { toSerializedSignature, type SignatureScheme } from '@mysten/sui/cryptography'; -import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519'; - -import { WalletSigner } from './WalletSigner'; - -export class LedgerSigner extends WalletSigner { - #suiLedgerClient: SuiLedgerClient | null; - readonly #connectToLedger: () => Promise; - readonly #derivationPath: string; - readonly #signatureScheme: SignatureScheme = 'ED25519'; - - constructor( - connectToLedger: () => Promise, - derivationPath: string, - client: SuiClient, - ) { - super(client); - this.#connectToLedger = connectToLedger; - this.#suiLedgerClient = null; - this.#derivationPath = derivationPath; - } - - async #initializeSuiLedgerClient() { - if (!this.#suiLedgerClient) { - // We want to make sure that there's only one connection established per Ledger signer - // instance since some methods make multiple calls like getAddress and signData - this.#suiLedgerClient = await this.#connectToLedger(); - } - return this.#suiLedgerClient; - } - - async getAddress(): Promise { - const ledgerClient = await this.#initializeSuiLedgerClient(); - const publicKeyResult = await ledgerClient.getPublicKey(this.#derivationPath); - const publicKey = new Ed25519PublicKey(publicKeyResult.publicKey); - return publicKey.toSuiAddress(); - } - - async getPublicKey(): Promise { - const ledgerClient = await this.#initializeSuiLedgerClient(); - const { publicKey } = await ledgerClient.getPublicKey(this.#derivationPath); - return new Ed25519PublicKey(publicKey); - } - - async signData(data: Uint8Array): Promise { - const ledgerClient = await this.#initializeSuiLedgerClient(); - const { signature } = await ledgerClient.signTransaction(this.#derivationPath, data); - const publicKey = await this.getPublicKey(); - return toSerializedSignature({ - signature, - signatureScheme: this.#signatureScheme, - publicKey, - }); - } - - connect(client: SuiClient) { - return new LedgerSigner(this.#connectToLedger, this.#derivationPath, client); - } -} diff --git a/apps/wallet/src/ui/app/QredoSigner.ts b/apps/wallet/src/ui/app/QredoSigner.ts deleted file mode 100644 index e50900a21040a..0000000000000 --- a/apps/wallet/src/ui/app/QredoSigner.ts +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type QredoSerializedUiAccount } from '_src/background/accounts/QredoAccount'; -import { API_ENV, networkNames } from '_src/shared/api-env'; -import { - type NetworkType, - type QredoAPI, - type TransactionInfoResponse, -} from '_src/shared/qredo-api'; -import { type SuiClient } from '@mysten/sui/client'; -import { messageWithIntent } from '@mysten/sui/cryptography'; -import { toBase64 } from '@mysten/sui/utils'; -import mitt from 'mitt'; - -import { WalletSigner } from './WalletSigner'; - -export class QredoActionIgnoredByUser extends Error {} - -const POLLING_INTERVAL = 4000; -const MAX_POLLING_TIMES = Math.ceil((60 * 1000 * 10) / POLLING_INTERVAL); - -function sleep() { - return new Promise((r) => setTimeout(r, POLLING_INTERVAL)); -} -export const API_ENV_TO_QREDO_NETWORK: Partial> = { - [API_ENV.mainnet]: 'mainnet', - [API_ENV.testNet]: 'testnet', - [API_ENV.devNet]: 'devnet', -}; -export class QredoSigner extends WalletSigner { - #qredoAccount: QredoSerializedUiAccount; - #qredoAPI: QredoAPI; - #network: NetworkType | null; - #apiEnv: API_ENV; - - constructor( - client: SuiClient, - account: QredoSerializedUiAccount, - qredoAPI: QredoAPI, - apiEnv: API_ENV, - ) { - super(client); - this.#qredoAccount = account; - this.#qredoAPI = qredoAPI; - this.#apiEnv = apiEnv; - this.#network = API_ENV_TO_QREDO_NETWORK[apiEnv] || null; - } - - async getAddress(): Promise { - return this.#qredoAccount.address; - } - - async signData(data: Uint8Array, clientIdentifier?: string): Promise { - let txInfo = await this.#createQredoTransaction(data, false, clientIdentifier); - try { - txInfo = await this.#pollForQredoTransaction( - txInfo, - (currentTxInfo) => - !currentTxInfo.sig && - ['created', 'authorized', 'pending', 'approved', 'queued', 'signed'].includes( - currentTxInfo.status, - ), - clientIdentifier, - ); - } finally { - if (clientIdentifier) { - QredoEvents.emit('qredoActionDone', { - clientIdentifier, - qredoTransactionID: txInfo.txID, - }); - } - } - if (['cancelled', 'expired', 'failed', 'rejected'].includes(txInfo.status)) { - throw new Error(`Transaction ${txInfo.status}`); - } - if (!txInfo.sig) { - throw new Error('Failed to retrieve signature'); - } - return txInfo.sig; - } - - signMessage: WalletSigner['signMessage'] = async (input, clientIdentifier) => { - const signature = await this.signData( - messageWithIntent('PersonalMessage', input.message), - clientIdentifier, - ); - return { - messageBytes: toBase64(input.message), - signature, - }; - }; - - signTransactionBlock: WalletSigner['signTransactionBlock'] = async (input, clientIdentifier) => { - const transactionBlockBytes = await this.prepareTransactionBlock(input.transactionBlock); - const signature = await this.signData( - messageWithIntent('TransactionData', transactionBlockBytes), - clientIdentifier, - ); - return { - transactionBlockBytes: toBase64(transactionBlockBytes), - signature, - }; - }; - - signAndExecuteTransactionBlock: WalletSigner['signAndExecuteTransactionBlock'] = async ( - { transactionBlock, options }, - clientIdentifier, - ) => { - let txInfo = await this.#createQredoTransaction( - messageWithIntent('TransactionData', await this.prepareTransactionBlock(transactionBlock)), - true, - clientIdentifier, - ); - try { - txInfo = await this.#pollForQredoTransaction( - txInfo, - (tx) => - [ - 'pending', - 'created', - 'authorized', - 'approved', - 'signed', - 'scheduled', - 'queued', - 'pushed', - ].includes(tx.status), - clientIdentifier, - ); - } finally { - if (clientIdentifier) { - QredoEvents.emit('qredoActionDone', { - clientIdentifier, - qredoTransactionID: txInfo.txID, - }); - } - } - if (txInfo.status !== 'confirmed') { - throw new Error(`Qredo transaction was ${txInfo.status}`); - } - if (!txInfo.txHash) { - throw new Error(`Digest is not set in Qredo transaction ${txInfo.txID}`); - } - return this.client.waitForTransaction({ - digest: txInfo.txHash, - options: options, - }); - }; - - connect(client: SuiClient): WalletSigner { - return new QredoSigner(client, this.#qredoAccount, this.#qredoAPI, this.#apiEnv); - } - - async #createQredoTransaction(intent: Uint8Array, broadcast: boolean, clientIdentifier?: string) { - if (!this.#network) { - throw new Error(`Unsupported network ${networkNames[this.#apiEnv]}`); - } - const qredoTransaction = await this.#qredoAPI.createTransaction({ - messageWithIntent: toBase64(intent), - network: this.#network, - broadcast, - from: await this.getAddress(), - }); - if (clientIdentifier) { - QredoEvents.emit('qredoTransactionCreated', { - qredoTransaction, - clientIdentifier, - }); - } - return qredoTransaction; - } - - async #pollForQredoTransaction( - qredoTransaction: TransactionInfoResponse, - keepPolling: (qredoTransaction: TransactionInfoResponse) => boolean, - clientIdentifier?: string, - ) { - let unsubscribeCallback; - let userIgnoredUpdates = false; - let promiseReject: () => void; - const userIgnoredPromise = new Promise((_, reject) => { - promiseReject = reject; - }); - if (clientIdentifier) { - unsubscribeCallback = (event: QredoEventsType['clientIgnoredUpdates']) => { - if (clientIdentifier === event.clientIdentifier) { - userIgnoredUpdates = true; - if (promiseReject) { - promiseReject(); - } - } - }; - QredoEvents.on('clientIgnoredUpdates', unsubscribeCallback); - } - let currentQredoTransaction = qredoTransaction; - let requestCounter = 0; - while ( - !userIgnoredUpdates && - keepPolling(currentQredoTransaction) && - requestCounter++ < MAX_POLLING_TIMES - ) { - try { - await Promise.race([sleep(), userIgnoredPromise]); - currentQredoTransaction = await Promise.race([ - this.#qredoAPI.getTransaction(currentQredoTransaction.txID), - userIgnoredPromise, - ]); - } catch (e) { - // maybe a network error - // TODO: stop if 500 or 404 etc? - } - } - if (clientIdentifier && unsubscribeCallback) { - QredoEvents.off('clientIgnoredUpdates', unsubscribeCallback); - } - if (userIgnoredUpdates) { - throw new QredoActionIgnoredByUser('User ignored transaction updates'); - } - return currentQredoTransaction; - } -} - -export type QredoEventsType = { - qredoTransactionCreated: { - qredoTransaction: TransactionInfoResponse; - clientIdentifier: string; - }; - qredoActionDone: { - clientIdentifier: string; - qredoTransactionID: string; - }; - clientIgnoredUpdates: { - clientIdentifier: string; - }; -}; -export const QredoEvents = mitt(); diff --git a/apps/wallet/src/ui/app/WalletSigner.ts b/apps/wallet/src/ui/app/WalletSigner.ts deleted file mode 100644 index 43bde1409db61..0000000000000 --- a/apps/wallet/src/ui/app/WalletSigner.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { bcs } from '@mysten/sui/bcs'; -import { - type DryRunTransactionBlockResponse, - type ExecuteTransactionRequestType, - type SuiClient, - type SuiTransactionBlockResponse, - type SuiTransactionBlockResponseOptions, -} from '@mysten/sui/client'; -import { messageWithIntent } from '@mysten/sui/cryptography'; -import { isTransaction, type Transaction } from '@mysten/sui/transactions'; -import { fromBase64, toBase64 } from '@mysten/sui/utils'; - -export type SignedTransaction = { - transactionBlockBytes: string; - signature: string; -}; - -export type SignedMessage = { - messageBytes: string; - signature: string; -}; - -export abstract class WalletSigner { - client: SuiClient; - - constructor(client: SuiClient) { - this.client = client; - } - - abstract signData(data: Uint8Array, clientIdentifier?: string): Promise; - - abstract getAddress(): Promise; - - async signMessage( - input: { message: Uint8Array }, - clientIdentifier?: string, - ): Promise { - const signature = await this.signData( - messageWithIntent('PersonalMessage', bcs.vector(bcs.u8()).serialize(input.message).toBytes()), - ); - - return { - messageBytes: toBase64(input.message), - signature, - }; - } - - protected async prepareTransactionBlock(transactionBlock: Uint8Array | Transaction | string) { - if (isTransaction(transactionBlock)) { - // If the sender has not yet been set on the transaction, then set it. - // NOTE: This allows for signing transactions with mis-matched senders, which is important for sponsored transactions. - transactionBlock.setSenderIfNotSet(await this.getAddress()); - return await transactionBlock.build({ - client: this.client, - }); - } - - if (typeof transactionBlock === 'string') { - return fromBase64(transactionBlock); - } - - if (transactionBlock instanceof Uint8Array) { - return transactionBlock; - } - throw new Error('Unknown transaction format'); - } - - async signTransactionBlock( - input: { - transactionBlock: Uint8Array | Transaction; - }, - clientIdentifier?: string, - ): Promise { - const bytes = await this.prepareTransactionBlock(input.transactionBlock); - const signature = await this.signData(messageWithIntent('TransactionData', bytes)); - - return { - transactionBlockBytes: toBase64(bytes), - signature, - }; - } - - async signAndExecuteTransactionBlock( - input: { - transactionBlock: Uint8Array | Transaction; - options?: SuiTransactionBlockResponseOptions; - requestType?: ExecuteTransactionRequestType; - }, - clientIdentifier?: string, - ): Promise { - const bytes = await this.prepareTransactionBlock(input.transactionBlock); - const signed = await this.signTransactionBlock({ - transactionBlock: bytes, - }); - - return this.client.executeTransactionBlock({ - transactionBlock: bytes, - signature: signed.signature, - options: input.options, - requestType: input.requestType, - }); - } - - async dryRunTransactionBlock(input: { - transactionBlock: Transaction | string | Uint8Array; - }): Promise { - return this.client.dryRunTransactionBlock({ - transactionBlock: await this.prepareTransactionBlock(input.transactionBlock), - }); - } -} diff --git a/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts b/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts deleted file mode 100644 index 7fec7c0fe1cda..0000000000000 --- a/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { type SuiClient } from '@mysten/sui/client'; - -import type { BackgroundClient } from '.'; -import { WalletSigner } from '../WalletSigner'; - -export class BackgroundServiceSigner extends WalletSigner { - readonly #account: SerializedUIAccount; - readonly #backgroundClient: BackgroundClient; - - constructor(account: SerializedUIAccount, backgroundClient: BackgroundClient, client: SuiClient) { - super(client); - this.#account = account; - this.#backgroundClient = backgroundClient; - } - - async getAddress(): Promise { - return this.#account.address; - } - - signData(data: Uint8Array): Promise { - return this.#backgroundClient.signData(this.#account.id, data); - } - - connect(client: SuiClient) { - return new BackgroundServiceSigner(this.#account, this.#backgroundClient, client); - } -} diff --git a/apps/wallet/src/ui/app/background-client/index.ts b/apps/wallet/src/ui/app/background-client/index.ts deleted file mode 100644 index 44ba8c295c0c2..0000000000000 --- a/apps/wallet/src/ui/app/background-client/index.ts +++ /dev/null @@ -1,636 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createMessage } from '_messages'; -import type { Message } from '_messages'; -import { PortStream } from '_messaging/PortStream'; -import { type BasePayload } from '_payloads'; -import { isLoadedFeaturesPayload } from '_payloads/feature-gating'; -import { isSetNetworkPayload, type SetNetworkPayload } from '_payloads/network'; -import { isPermissionRequests } from '_payloads/permissions'; -import type { GetPermissionRequests, PermissionResponse } from '_payloads/permissions'; -import type { DisconnectApp } from '_payloads/permissions/DisconnectApp'; -import { isUpdateActiveOrigin } from '_payloads/tabs/updateActiveOrigin'; -import type { GetTransactionRequests } from '_payloads/transactions/ui/GetTransactionRequests'; -import { isGetTransactionRequestsResponse } from '_payloads/transactions/ui/GetTransactionRequestsResponse'; -import type { TransactionRequestResponse } from '_payloads/transactions/ui/TransactionRequestResponse'; -import { changeActiveNetwork, setActiveOrigin } from '_redux/slices/app'; -import { setPermissions } from '_redux/slices/permissions'; -import { setTransactionRequests } from '_redux/slices/transaction-requests'; -import { type MnemonicSerializedUiAccount } from '_src/background/accounts/MnemonicAccount'; -import type { NetworkEnvType } from '_src/shared/api-env'; -import { - isMethodPayload, - type MethodPayload, - type UIAccessibleEntityType, -} from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { - isQredoConnectPayload, - type QredoConnectPayload, -} from '_src/shared/messaging/messages/payloads/QredoConnect'; -import { type SignedMessage, type SignedTransaction } from '_src/ui/app/WalletSigner'; -import type { AppDispatch } from '_store'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { toBase64 } from '@mysten/sui/utils'; -import { type QueryKey } from '@tanstack/react-query'; -import { lastValueFrom, map, take } from 'rxjs'; - -import { growthbook } from '../experimentation/feature-gating'; -import { accountsQueryKey } from '../helpers/query-client-keys'; -import { queryClient } from '../helpers/queryClient'; -import { accountSourcesQueryKey } from '../hooks/useAccountSources'; - -const entitiesToClientQueryKeys: Record = { - accounts: accountsQueryKey, - accountSources: accountSourcesQueryKey, -}; - -export class BackgroundClient { - private _portStream: PortStream | null = null; - private _dispatch: AppDispatch | null = null; - private _initialized = false; - - public init(dispatch: AppDispatch) { - if (this._initialized) { - throw new Error('[BackgroundClient] already initialized'); - } - this._initialized = true; - this._dispatch = dispatch; - this.createPortStream(); - return Promise.all([ - this.sendGetPermissionRequests(), - this.sendGetTransactionRequests(), - this.loadFeatures(), - this.getNetwork(), - ]).then(() => undefined); - } - - public sendPermissionResponse( - id: string, - accounts: string[], - allowed: boolean, - responseDate: string, - ) { - this.sendMessage( - createMessage({ - id, - type: 'permission-response', - accounts, - allowed, - responseDate, - }), - ); - } - - public sendGetPermissionRequests() { - return lastValueFrom( - this.sendMessage( - createMessage({ - type: 'get-permission-requests', - }), - ).pipe(take(1)), - ); - } - - public sendTransactionRequestResponse( - txID: string, - approved: boolean, - txResult?: SuiTransactionBlockResponse | SignedMessage, - txResultError?: string, - txSigned?: SignedTransaction, - ) { - this.sendMessage( - createMessage({ - type: 'transaction-request-response', - approved, - txID, - txResult, - txResultError, - txSigned, - }), - ); - } - - public sendGetTransactionRequests() { - return lastValueFrom( - this.sendMessage( - createMessage({ - type: 'get-transaction-requests', - }), - ).pipe(take(1)), - ); - } - - /** - * Disconnect a dapp, if specificAccounts contains accounts then only those accounts will be disconnected. - * @param origin The origin of the dapp - * @param specificAccounts Accounts to disconnect. If not provided or it's an empty array all accounts will be disconnected - */ - public async disconnectApp(origin: string, specificAccounts?: string[]) { - await lastValueFrom( - this.sendMessage( - createMessage({ - type: 'disconnect-app', - origin, - specificAccounts, - }), - ).pipe(take(1)), - ); - } - - public clearWallet() { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'clearWallet', - args: {}, - }), - ).pipe(take(1)), - ); - } - - public signData(addressOrID: string, data: Uint8Array): Promise { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'signData', - args: { data: toBase64(data), id: addressOrID }, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isMethodPayload(payload, 'signDataResponse')) { - return payload.args.signature; - } - throw new Error('Error unknown response for signData message'); - }), - ), - ); - } - - public setActiveNetworkEnv(network: NetworkEnvType) { - return lastValueFrom( - this.sendMessage( - createMessage({ - type: 'set-network', - network, - }), - ).pipe(take(1)), - ); - } - - public selectAccount(accountID: string) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'switchAccount', - args: { accountID }, - }), - ).pipe(take(1)), - ); - } - - public verifyPassword(args: MethodPayload<'verifyPassword'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'verifyPassword', - args, - }), - ).pipe(take(1)), - ); - } - - public exportAccountKeyPair(args: MethodPayload<'getAccountKeyPair'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'getAccountKeyPair', - args, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isMethodPayload(payload, 'getAccountKeyPairResponse')) { - return payload.args; - } - throw new Error('Error unknown response for export account message'); - }), - ), - ); - } - - public fetchPendingQredoConnectRequest(requestID: string) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'qredo-connect', - method: 'getPendingRequest', - args: { requestID }, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isQredoConnectPayload(payload, 'getPendingRequestResponse')) { - return payload.args.request; - } - throw new Error('Error unknown response for fetch pending qredo requests message'); - }), - ), - ); - } - - public getQredoConnectionInfo(qredoID: string, refreshAccessToken = false) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'qredo-connect', - method: 'getQredoInfo', - args: { qredoID, refreshAccessToken }, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isQredoConnectPayload(payload, 'getQredoInfoResponse')) { - return payload.args; - } - throw new Error('Error unknown response for get qredo info message'); - }), - ), - ); - } - - public acceptQredoConnection(args: QredoConnectPayload<'acceptQredoConnection'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'qredo-connect', - method: 'acceptQredoConnection', - args, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isQredoConnectPayload(payload, 'acceptQredoConnectionResponse')) { - return payload.args.accounts; - } - throw new Error('Error unknown response for accept qredo connection'); - }), - ), - ); - } - - public rejectQredoConnection(args: QredoConnectPayload<'rejectQredoConnection'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'qredo-connect', - method: 'rejectQredoConnection', - args, - }), - ).pipe(take(1)), - ); - } - - public getStoredEntities(type: UIAccessibleEntityType): Promise { - return lastValueFrom( - this.sendMessage( - createMessage>({ - method: 'getStoredEntities', - type: 'method-payload', - args: { type }, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (!isMethodPayload(payload, 'storedEntitiesResponse')) { - throw new Error('Unknown response'); - } - if (type !== payload.args.type) { - throw new Error(`unexpected entity type response ${payload.args.type}`); - } - return payload.args.entities; - }), - ), - ); - } - - public createMnemonicAccountSource(inputs: { password: string; entropy?: string }) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - method: 'createAccountSource', - type: 'method-payload', - args: { type: 'mnemonic', params: inputs }, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (!isMethodPayload(payload, 'accountSourceCreationResponse')) { - throw new Error('Unknown response'); - } - if ('mnemonic' !== payload.args.accountSource.type) { - throw new Error( - `Unexpected account source type response ${payload.args.accountSource.type}`, - ); - } - return payload.args.accountSource as unknown as MnemonicSerializedUiAccount; - }), - ), - ); - } - - public createAccounts(inputs: MethodPayload<'createAccounts'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - method: 'createAccounts', - type: 'method-payload', - args: inputs, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (!isMethodPayload(payload, 'accountsCreatedResponse')) { - throw new Error('Unknown response'); - } - if (inputs.type !== payload.args.accounts[0]?.type) { - throw new Error(`Unexpected accounts type response ${payload.args.accounts[0]?.type}`); - } - return payload.args.accounts; - }), - ), - ); - } - - public unlockAccountSourceOrAccount( - inputs: MethodPayload<'unlockAccountSourceOrAccount'>['args'], - ) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'unlockAccountSourceOrAccount', - args: inputs, - }), - ).pipe(take(1)), - ); - } - - public lockAccountSourceOrAccount({ id }: MethodPayload<'lockAccountSourceOrAccount'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'lockAccountSourceOrAccount', - args: { id }, - }), - ).pipe(take(1)), - ); - } - - public setAccountNickname({ id, nickname }: MethodPayload<'setAccountNickname'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'setAccountNickname', - args: { id, nickname }, - }), - ).pipe(take(1)), - ); - } - - public getStorageMigrationStatus() { - return lastValueFrom( - this.sendMessage( - createMessage>({ - method: 'getStorageMigrationStatus', - type: 'method-payload', - args: null, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (!isMethodPayload(payload, 'storageMigrationStatus')) { - throw new Error('Unknown response'); - } - return payload.args.status; - }), - ), - ); - } - - public doStorageMigration(inputs: MethodPayload<'doStorageMigration'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'doStorageMigration', - args: inputs, - }), - ).pipe(take(1)), - ); - } - - /** - * Wallet wasn't storing the public key of ledger accounts, but we need it to send it to the dapps. - * Use this function to update the public keys whenever wallet has access to them. - */ - public storeLedgerAccountsPublicKeys( - args: MethodPayload<'storeLedgerAccountsPublicKeys'>['args'], - ) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'storeLedgerAccountsPublicKeys', - args, - }), - ).pipe(take(1)), - ); - } - - public getAccountSourceEntropy(args: MethodPayload<'getAccountSourceEntropy'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'getAccountSourceEntropy', - args, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isMethodPayload(payload, 'getAccountSourceEntropyResponse')) { - return payload.args; - } - throw new Error('Unexpected response type'); - }), - ), - ); - } - - public getAutoLockMinutes() { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'getAutoLockMinutes', - args: {}, - }), - ).pipe( - take(1), - map(({ payload }) => { - if (isMethodPayload(payload, 'getAutoLockMinutesResponse')) { - return payload.args.minutes; - } - throw new Error('Unexpected response type'); - }), - ), - ); - } - - public setAutoLockMinutes(args: MethodPayload<'setAutoLockMinutes'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'setAutoLockMinutes', - args, - }), - ).pipe(take(1)), - ); - } - - public notifyUserActive() { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'notifyUserActive', - args: {}, - }), - ).pipe(take(1)), - ); - } - - public resetPassword(args: MethodPayload<'resetPassword'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'resetPassword', - args, - }), - ).pipe(take(1)), - ); - } - - public verifyPasswordRecoveryData(args: MethodPayload<'verifyPasswordRecoveryData'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'verifyPasswordRecoveryData', - args, - }), - ).pipe(take(1)), - ); - } - - public removeAccount(args: MethodPayload<'removeAccount'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'removeAccount', - args, - }), - ).pipe(take(1)), - ); - } - - public acknowledgeZkLoginWarning(args: MethodPayload<'acknowledgeZkLoginWarning'>['args']) { - return lastValueFrom( - this.sendMessage( - createMessage>({ - type: 'method-payload', - method: 'acknowledgeZkLoginWarning', - args, - }), - ).pipe(take(1)), - ); - } - - private loadFeatures() { - return lastValueFrom( - this.sendMessage( - createMessage({ - type: 'get-features', - }), - ).pipe(take(1)), - ); - } - - private getNetwork() { - return lastValueFrom( - this.sendMessage( - createMessage({ - type: 'get-network', - }), - ).pipe(take(1)), - ); - } - - private handleIncomingMessage(msg: Message) { - if (!this._initialized || !this._dispatch) { - throw new Error('BackgroundClient is not initialized to handle incoming messages'); - } - const { payload } = msg; - let action; - if (isPermissionRequests(payload)) { - action = setPermissions(payload.permissions); - } else if (isGetTransactionRequestsResponse(payload)) { - action = setTransactionRequests(payload.txRequests); - } else if (isUpdateActiveOrigin(payload)) { - action = setActiveOrigin(payload); - } else if (isLoadedFeaturesPayload(payload)) { - growthbook.setAttributes(payload.attributes); - growthbook.setFeatures(payload.features); - } else if (isSetNetworkPayload(payload)) { - action = changeActiveNetwork({ - network: payload.network, - }); - } else if (isMethodPayload(payload, 'entitiesUpdated')) { - const entitiesQueryKey = entitiesToClientQueryKeys[payload.args.type]; - if (entitiesQueryKey) { - queryClient.invalidateQueries({ queryKey: entitiesQueryKey }); - } - } - if (action) { - this._dispatch(action); - } - } - - private createPortStream() { - this._portStream = PortStream.connectToBackgroundService('sui_ui<->background'); - this._portStream.onDisconnect.subscribe(() => { - this.createPortStream(); - }); - this._portStream.onMessage.subscribe((msg) => this.handleIncomingMessage(msg)); - } - - private sendMessage(msg: Message) { - if (this._portStream?.connected) { - return this._portStream.sendMessage(msg); - } else { - throw new Error('Failed to send message to background service. Port not connected.'); - } - } -} diff --git a/apps/wallet/src/ui/app/components/AccountBadge.tsx b/apps/wallet/src/ui/app/components/AccountBadge.tsx deleted file mode 100644 index 02323ec68fbe7..0000000000000 --- a/apps/wallet/src/ui/app/components/AccountBadge.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type AccountType } from '_src/background/accounts/Account'; - -import { BadgeLabel } from './BadgeLabel'; - -type AccountBadgeProps = { - accountType: AccountType; -}; - -const TYPE_TO_TEXT: Record = { - ledger: 'Ledger', - imported: 'Imported', - qredo: 'Qredo', - 'mnemonic-derived': null, - zkLogin: 'zkLogin', -}; - -export function AccountBadge({ accountType }: AccountBadgeProps) { - const badgeText = TYPE_TO_TEXT[accountType]; - - if (!badgeText) return null; - - return ; -} diff --git a/apps/wallet/src/ui/app/components/AccountListItem.tsx b/apps/wallet/src/ui/app/components/AccountListItem.tsx deleted file mode 100644 index 9052cffdb3546..0000000000000 --- a/apps/wallet/src/ui/app/components/AccountListItem.tsx +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { Check12, Copy12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; - -import { useCopyToClipboard } from '../hooks/useCopyToClipboard'; -import { Text } from '../shared/text'; -import { AccountBadge } from './AccountBadge'; - -export type AccountItemProps = { - account: SerializedUIAccount; - onAccountSelected: (account: SerializedUIAccount) => void; -}; - -/** @deprecated - use AccountListItem from the `accounts` folder **/ -export function AccountListItem({ account, onAccountSelected }: AccountItemProps) { - const { address, type, selected } = account; - const copy = useCopyToClipboard(address, { - copySuccessMessage: 'Address Copied', - }); - const domainName = useResolveSuiNSName(address); - - return ( -
  • - -
  • - ); -} diff --git a/apps/wallet/src/ui/app/components/BadgeLabel.tsx b/apps/wallet/src/ui/app/components/BadgeLabel.tsx deleted file mode 100644 index 00154b0ed937a..0000000000000 --- a/apps/wallet/src/ui/app/components/BadgeLabel.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import { type ReactNode } from 'react'; - -type BadgeLabelProps = { - label: ReactNode; -}; - -export function BadgeLabel({ label }: BadgeLabelProps) { - return ( -
    - - {label} - -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/DAppInfoCard.tsx b/apps/wallet/src/ui/app/components/DAppInfoCard.tsx deleted file mode 100644 index 5edffd9303569..0000000000000 --- a/apps/wallet/src/ui/app/components/DAppInfoCard.tsx +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type PermissionType } from '_src/shared/messaging/messages/payloads/permissions'; -import { getValidDAppUrl } from '_src/shared/utils'; -import { CheckFill16 } from '@mysten/icons'; -import cn from 'clsx'; - -import { useAccountByAddress } from '../hooks/useAccountByAddress'; -import { Heading } from '../shared/heading'; -import { Link } from '../shared/Link'; -import { AccountIcon } from './accounts/AccountIcon'; -import { AccountItem } from './accounts/AccountItem'; -import { LockUnlockButton } from './accounts/LockUnlockButton'; -import { useUnlockAccount } from './accounts/UnlockAccountContext'; -import Alert from './alert'; -import { DAppPermissionsList } from './DAppPermissionsList'; -import { SummaryCard } from './SummaryCard'; - -export type DAppInfoCardProps = { - name: string; - url: string; - iconUrl?: string; - connectedAddress?: string; - permissions?: PermissionType[]; - showSecurityWarning?: boolean; -}; - -export function DAppInfoCard({ - name, - url, - iconUrl, - connectedAddress, - permissions, - showSecurityWarning, -}: DAppInfoCardProps) { - const validDAppUrl = getValidDAppUrl(url); - const appHostname = validDAppUrl?.hostname ?? url; - const { data: account } = useAccountByAddress(connectedAddress); - const { unlockAccount, lockAccount, isPending, accountToUnlock } = useUnlockAccount(); - - return ( -
    -
    -
    - {iconUrl ? {name} : null} -
    -
    -
    - - {name} - -
    -
    - -
    -
    -
    - {connectedAddress && account ? ( - } - accountID={account.id} - disabled={account.isLocked} - after={ -
    - {account.isLocked ? ( -
    - { - // prevent the account from being selected when clicking the lock button - e.stopPropagation(); - if (account.isLocked) { - unlockAccount(account); - } else { - lockAccount(account); - } - }} - /> -
    - ) : null} - -
    - } - hideCopy - hideExplorerLink - /> - ) : null} - <> - {showSecurityWarning && ( - -
    - Unable to verify site security - An error occurred while validating the integrity of this website. Please proceed with - caution. -
    -
    - )} - {permissions?.length ? ( - } - boxShadow - /> - ) : null} - -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/DAppPermissionsList.tsx b/apps/wallet/src/ui/app/components/DAppPermissionsList.tsx deleted file mode 100644 index 5de7424dcab31..0000000000000 --- a/apps/wallet/src/ui/app/components/DAppPermissionsList.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { PermissionType } from '_messages/payloads/permissions'; -import { CheckFill12 } from '@mysten/icons'; - -import { Text } from '../shared/text'; - -export type DAppPermissionsListProps = { - permissions: PermissionType[]; -}; - -const permissionTypeToTxt: Record = { - viewAccount: 'Share wallet address', - suggestTransactions: 'Suggest transactions to approve', -}; - -export function DAppPermissionsList({ permissions }: DAppPermissionsListProps) { - return ( -
      - {permissions.map((aPermission) => ( -
    • - - - {permissionTypeToTxt[aPermission]} - -
    • - ))} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/HideShowDisplayBox.tsx b/apps/wallet/src/ui/app/components/HideShowDisplayBox.tsx deleted file mode 100644 index 4b18247d496b6..0000000000000 --- a/apps/wallet/src/ui/app/components/HideShowDisplayBox.tsx +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Copy16, EyeClose16, EyeOpen16 } from '@mysten/icons'; -import { cx } from 'class-variance-authority'; -import { useEffect, useState } from 'react'; - -import { useCopyToClipboard } from '../hooks/useCopyToClipboard'; -import { Link } from '../shared/Link'; -import { Text } from '../shared/text'; - -const AUTO_HIDE_INTERVAL = 3 * 60 * 1000; - -export type HideShowDisplayBoxProps = { - value: string | string[]; - hideCopy?: boolean; - copiedMessage?: string; -}; - -export function HideShowDisplayBox({ - value, - hideCopy = false, - copiedMessage, -}: HideShowDisplayBoxProps) { - const [valueHidden, setValueHidden] = useState(true); - const copyCallback = useCopyToClipboard( - hideCopy ? '' : typeof value === 'string' ? value : value.join(' '), - { - copySuccessMessage: copiedMessage, - }, - ); - useEffect(() => { - const updateOnVisibilityChange = () => { - if (document.visibilityState === 'hidden') { - setValueHidden(true); - } - }; - document.addEventListener('visibilitychange', updateOnVisibilityChange); - return () => { - document.removeEventListener('visibilitychange', updateOnVisibilityChange); - }; - }, []); - useEffect(() => { - let timeout: number; - if (!valueHidden) { - timeout = window.setTimeout(() => { - setValueHidden(true); - }, AUTO_HIDE_INTERVAL); - } - return () => { - if (timeout) { - clearTimeout(timeout); - } - }; - }, [valueHidden]); - return ( -
    -
    - {valueHidden ? null : ( -
    - - {typeof value === 'string' - ? value - : value.map((aValue, index) => ( - {(index > 0 ? ' ' : '') + aValue} - ))} - -
    - )} -
    -
    -
    -
    -
    -
    -
    -
    - {!hideCopy ? ( - } - onClick={copyCallback} - /> - ) : null} -
    -
    - : } - onClick={() => setValueHidden((v) => !v)} - /> -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/IconButton.tsx b/apps/wallet/src/ui/app/components/IconButton.tsx deleted file mode 100644 index a2429f2518d9f..0000000000000 --- a/apps/wallet/src/ui/app/components/IconButton.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; - -import { ButtonOrLink, type ButtonOrLinkProps } from '../shared/utils/ButtonOrLink'; - -interface IconButtonProps extends ButtonOrLinkProps, VariantProps { - icon: JSX.Element; -} - -const buttonStyles = cva( - [ - 'flex items-center rounded-sm bg-transparent border-0 p-0 text-hero-darkest/40 hover:text-hero-darkest/50 transition cursor-pointer', - ], - { - variants: { - variant: { - transparent: '', - subtle: 'hover:bg-hero-darkest/10', - }, - }, - defaultVariants: { - variant: 'subtle', - }, - }, -); - -export function IconButton({ onClick, icon, variant, ...buttonOrLinkProps }: IconButtonProps) { - return ( - - ); -} diff --git a/apps/wallet/src/ui/app/components/LabelValueItem.tsx b/apps/wallet/src/ui/app/components/LabelValueItem.tsx deleted file mode 100644 index ede7f775cba46..0000000000000 --- a/apps/wallet/src/ui/app/components/LabelValueItem.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import cl from 'clsx'; -import { type ReactNode } from 'react'; - -export type LabelValueItemProps = { - label: string; - value: ReactNode; - multiline?: boolean; - parseUrl?: boolean; -}; - -export function LabelValueItem({ label, value, multiline = false }: LabelValueItemProps) { - return value ? ( -
    -
    - - {label} - -
    -
    - - {value} - -
    -
    - ) : null; -} diff --git a/apps/wallet/src/ui/app/components/LabelValuesContainer.tsx b/apps/wallet/src/ui/app/components/LabelValuesContainer.tsx deleted file mode 100644 index 8c9005949c878..0000000000000 --- a/apps/wallet/src/ui/app/components/LabelValuesContainer.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type ReactNode } from 'react'; - -export type LabelValuesContainerProps = { - children: ReactNode; -}; - -export function LabelValuesContainer({ children }: LabelValuesContainerProps) { - return
    {children}
    ; -} diff --git a/apps/wallet/src/ui/app/components/PasswordInputDialog.tsx b/apps/wallet/src/ui/app/components/PasswordInputDialog.tsx deleted file mode 100644 index 66d5f15d3d258..0000000000000 --- a/apps/wallet/src/ui/app/components/PasswordInputDialog.tsx +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useBackgroundClient } from '_src/ui/app/hooks/useBackgroundClient'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import FieldLabel from '_src/ui/app/shared/field-label'; -import { Heading } from '_src/ui/app/shared/heading'; -import { PasswordInputField } from '_src/ui/app/shared/input/password'; -import { Text } from '_src/ui/app/shared/text'; -import { ArrowLeft16, ArrowRight16 } from '@mysten/icons'; -import classNames from 'clsx'; -import { ErrorMessage, Form, Formik } from 'formik'; -import { toast } from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; -import { object, string as YupString } from 'yup'; - -import Alert from './alert'; - -const validation = object({ - password: YupString().ensure().required().label('Password'), -}); - -export type PasswordExportDialogProps = { - title: string; - continueLabel?: string; - showArrowIcon?: boolean; - onPasswordVerified: (password: string) => Promise | void; - onBackClicked?: () => void; - showBackButton?: boolean; - spacing?: boolean; - background?: boolean; - legacyAccounts?: boolean; -}; - -/** @deprecated - use UnlockAccountModal instead **/ -export function PasswordInputDialog({ - title, - continueLabel = 'Continue', - showArrowIcon = false, - spacing = false, - background = false, - onPasswordVerified, - onBackClicked, - showBackButton = false, - legacyAccounts = false, -}: PasswordExportDialogProps) { - const navigate = useNavigate(); - const backgroundService = useBackgroundClient(); - return ( - { - try { - await backgroundService.verifyPassword({ password, legacyAccounts }); - try { - await onPasswordVerified(password); - } catch (e) { - toast.error((e as Error).message || 'Wrong password'); - } - } catch (e) { - setFieldError('password', (e as Error).message || 'Wrong password'); - } - }} - validationSchema={validation} - validateOnMount - > - {({ isSubmitting, isValid }) => ( -
    -
    - - {title} - -
    -
    - - - {error}} name="password" /> - -
    - - This is the password you currently use to lock and unlock your Sui wallet. - -
    -
    -
    - {showBackButton ? ( -
    -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/SectionHeader.tsx b/apps/wallet/src/ui/app/components/SectionHeader.tsx deleted file mode 100644 index 6abf49cc5cd2e..0000000000000 --- a/apps/wallet/src/ui/app/components/SectionHeader.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '../shared/text'; - -export function SectionHeader({ title }: { title: string }) { - return ( -
    -
    - - {title} - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/SummaryCard.tsx b/apps/wallet/src/ui/app/components/SummaryCard.tsx deleted file mode 100644 index 1d0976e91da8f..0000000000000 --- a/apps/wallet/src/ui/app/components/SummaryCard.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import clsx from 'clsx'; -import type { ReactNode } from 'react'; - -import { Text } from '../shared/text'; - -export type SummaryCardProps = { - header?: string; - body: ReactNode; - footer?: ReactNode; - minimalPadding?: boolean; - showDivider?: boolean; - noBorder?: boolean; - boxShadow?: boolean; -}; - -export function SummaryCard({ - body, - header, - footer, - minimalPadding, - showDivider = false, - noBorder = false, - boxShadow = false, -}: SummaryCardProps) { - return ( -
    - {header ? ( -
    - - {header} - -
    - ) : null} -
    - {body} -
    - {footer ? ( -
    - {footer} -
    - ) : null} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/WalletListSelect.tsx b/apps/wallet/src/ui/app/components/WalletListSelect.tsx deleted file mode 100644 index fe6733464a5c1..0000000000000 --- a/apps/wallet/src/ui/app/components/WalletListSelect.tsx +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cx } from 'class-variance-authority'; -import { useMemo } from 'react'; - -import { useAccounts } from '../hooks/useAccounts'; -import { Link } from '../shared/Link'; -import { SummaryCard } from './SummaryCard'; -import { WalletListSelectItem, type WalletListSelectItemProps } from './WalletListSelectItem'; - -export type WalletListSelectProps = { - title: string; - values: string[]; - visibleValues?: string[]; - mode?: WalletListSelectItemProps['mode']; - disabled?: boolean; - onChange: (values: string[]) => void; - boxShadow?: boolean; -}; - -export function WalletListSelect({ - title, - values, - visibleValues, - mode = 'select', - disabled = false, - onChange, - boxShadow = false, -}: WalletListSelectProps) { - const { data: accounts } = useAccounts(); - const filteredAccounts = useMemo(() => { - if (!accounts) { - return []; - } - if (visibleValues) { - return accounts.filter(({ address }) => visibleValues.includes(address)); - } - return accounts; - }, [accounts, visibleValues]); - return ( - - {filteredAccounts.map(({ address }) => ( -
  • { - if (disabled) { - return; - } - const newValues = []; - let found = false; - for (const anAddress of values) { - if (anAddress === address) { - found = true; - continue; - } - newValues.push(anAddress); - } - if (!found) { - newValues.push(address); - } - onChange(newValues); - }} - > - -
  • - ))} - - } - footer={ - mode === 'select' ? ( -
    -
    - {filteredAccounts.length > 1 ? ( - onChange(filteredAccounts.map(({ address }) => address))} - /> - ) : null} -
    -
    - ) : null - } - minimalPadding - boxShadow={boxShadow} - /> - ); -} diff --git a/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx b/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx deleted file mode 100644 index fe583136f5000..0000000000000 --- a/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { CheckFill16, XFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import { cva, cx, type VariantProps } from 'class-variance-authority'; -import { useEffect, useRef } from 'react'; - -import { Text } from '../shared/text'; - -const styles = cva('transition flex flex-row flex-nowrap items-center gap-3 py-2 cursor-pointer', { - variants: { - selected: { - true: '', - false: '', - }, - mode: { - select: '', - disconnect: '', - }, - disabled: { - true: '', - false: '', - }, - }, - compoundVariants: [ - { - mode: 'select', - disabled: false, - className: 'hover:text-steel-dark', - }, - { mode: 'select', selected: true, className: 'text-steel-darker' }, - { mode: 'select', selected: false, className: 'text-steel-dark' }, - { - mode: 'disconnect', - selected: true, - className: 'text-issue-dark', - }, - { - mode: 'disconnect', - selected: false, - className: 'text-steel-darker', - }, - ], -}); -type StyleProps = VariantProps; -export interface WalletListSelectItemProps extends Omit { - selected: NonNullable; - mode: NonNullable; - address: string; - isNew?: boolean; -} - -export function WalletListSelectItem({ - address, - selected, - mode, - disabled = false, - isNew = false, -}: WalletListSelectItemProps) { - const elementRef = useRef(null); - useEffect(() => { - const timeout = setTimeout(() => { - if (elementRef.current && isNew) { - elementRef.current.scrollIntoView({ - behavior: 'smooth', - block: 'center', - }); - } - }, 80); - return () => { - clearTimeout(timeout); - }; - }, [isNew]); - - const isDisconnect = mode === 'disconnect'; - const isSelect = mode === 'select'; - - return ( -
    - {isSelect ? ( - - ) : null} - {isDisconnect && selected ? ( - - ) : null} - - {formatAddress(address)} - - {isDisconnect && !selected ? ( -
    - - Disconnect - -
    - ) : null} - {isSelect && isNew ? ( -
    - - NEW - -
    - ) : null} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx b/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx deleted file mode 100644 index 09095b7bcb2a5..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { isZkLoginAccountSerializedUI } from '_src/background/accounts/zklogin/ZkLoginAccount'; -import { - LedgerLogo17, - LogoGoogle, - LogoQredo, - LogoTwitch, - SocialFacebook24, - SocialKakao24, - Sui, -} from '@mysten/icons'; - -function SuiIcon() { - return ( -
    - -
    - ); -} - -function ProviderIcon({ provider }: { provider: string }) { - switch (provider) { - case 'google': - return ; - case 'twitch': - return ; - case 'facebook': - return ; - case 'kakao': - return ; - default: - return ; - } -} - -export function AccountIcon({ account }: { account: SerializedUIAccount }) { - if (isZkLoginAccountSerializedUI(account)) { - return ; - } - if (account.type === 'qredo') { - return ; - } - if (account.type === 'ledger') { - return ; - } - return ; -} diff --git a/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx b/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx deleted file mode 100644 index 629920e34da76..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { Text } from '_src/ui/app/shared/text'; -import { ArrowUpRight12, Copy12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import cn from 'clsx'; -import { forwardRef, type ReactNode } from 'react'; - -import { getAccountBackgroundByType } from '../../helpers/accounts'; -import { useAccounts } from '../../hooks/useAccounts'; -import { useCopyToClipboard } from '../../hooks/useCopyToClipboard'; -import { useExplorerLink } from '../../hooks/useExplorerLink'; -import { ExplorerLinkType } from '../explorer-link/ExplorerLinkType'; -import { IconButton } from '../IconButton'; -import { EditableAccountName } from './EditableAccountName'; - -interface AccountItemProps { - accountID: string; - icon?: ReactNode; - after?: ReactNode; - footer?: ReactNode; - disabled?: boolean; - gradient?: boolean; - selected?: boolean; // whether the account is selected in the context of a multi-select - isActiveAccount?: boolean; // whether the account is the active account in the context of the account list - background?: 'gradient'; - editable?: boolean; - hideExplorerLink?: boolean; - hideCopy?: boolean; -} - -export const AccountItem = forwardRef( - ( - { - background, - selected, - isActiveAccount, - disabled, - icon, - accountID, - after, - footer, - editable, - hideExplorerLink, - hideCopy, - ...props - }, - ref, - ) => { - const { data: accounts } = useAccounts(); - const account = accounts?.find((account) => account.id === accountID); - const domainName = useResolveSuiNSName(account?.address); - const accountName = account?.nickname ?? domainName ?? formatAddress(account?.address || ''); - const copyAddress = useCopyToClipboard(account?.address || '', { - copySuccessMessage: 'Address copied', - }); - const explorerHref = useExplorerLink({ - type: ExplorerLinkType.address, - address: account?.address, - }); - if (!account) return null; - - return ( -
    -
    -
    {icon}
    -
    - {!isActiveAccount && !editable ? ( - - {accountName} - - ) : ( - - )} -
    - - {formatAddress(account.address)} - -
    - {hideCopy ? null : ( - } - onClick={copyAddress} - /> - )} - {hideExplorerLink || !explorerHref ? null : ( - } - onClick={(e) => e.stopPropagation()} - /> - )} -
    -
    -
    - {after} -
    - {footer} -
    - ); - }, -); diff --git a/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx b/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx deleted file mode 100644 index 1972a4ce62e7b..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { AccountIcon } from '_components/accounts/AccountIcon'; -import { LockUnlockButton } from '_components/accounts/LockUnlockButton'; -import { useUnlockAccount } from '_components/accounts/UnlockAccountContext'; -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { CheckFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import clsx from 'clsx'; - -interface Props { - account: SerializedUIAccount; - disabled: boolean; - selected?: boolean; - showLock?: boolean; -} - -export function AccountItemApproveConnection({ account, selected, disabled, showLock }: Props) { - const domainName = useResolveSuiNSName(account?.address); - const accountName = account?.nickname ?? domainName ?? formatAddress(account?.address || ''); - const { unlockAccount, lockAccount, isPending, accountToUnlock } = useUnlockAccount(); - - return ( -
    - - -
    -
    - {accountName} -
    - -
    - {formatAddress(account.address)} -
    -
    - -
    - {showLock ? ( -
    - { - // prevent the account from being selected when clicking the lock button - e.stopPropagation(); - if (account.isLocked) { - unlockAccount(account); - } else { - lockAccount(account); - } - }} - /> -
    - ) : null} - -
    - -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/AccountListItem.tsx b/apps/wallet/src/ui/app/components/accounts/AccountListItem.tsx deleted file mode 100644 index ac07b3e812ef4..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountListItem.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; - -import { useActiveAccount } from '../../hooks/useActiveAccount'; -import { AccountIcon } from './AccountIcon'; -import { AccountItem } from './AccountItem'; -import { LockUnlockButton } from './LockUnlockButton'; -import { useUnlockAccount } from './UnlockAccountContext'; - -type AccountListItemProps = { - account: SerializedUIAccount; - editable?: boolean; - showLock?: boolean; - hideCopy?: boolean; - hideExplorerLink?: boolean; -}; - -export function AccountListItem({ - account, - editable, - showLock, - hideCopy, - hideExplorerLink, -}: AccountListItemProps) { - const activeAccount = useActiveAccount(); - const { unlockAccount, lockAccount, isPending, accountToUnlock } = useUnlockAccount(); - - return ( - } - isActiveAccount={account.address === activeAccount?.address} - after={ - showLock ? ( -
    -
    - { - // prevent the account from being selected when clicking the lock button - e.stopPropagation(); - if (account.isLocked) { - unlockAccount(account); - } else { - lockAccount(account); - } - }} - /> -
    -
    - ) : null - } - accountID={account.id} - editable={editable} - hideCopy={hideCopy} - hideExplorerLink={hideExplorerLink} - /> - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/AccountMultiSelect.tsx b/apps/wallet/src/ui/app/components/accounts/AccountMultiSelect.tsx deleted file mode 100644 index 3f0cfd2b56d48..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountMultiSelect.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { AccountItemApproveConnection } from '_components/accounts/AccountItemApproveConnection'; -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import * as ToggleGroup from '@radix-ui/react-toggle-group'; -import { useState } from 'react'; - -import { Button } from '../../shared/ButtonUI'; - -type AccountMultiSelectProps = { - accounts: SerializedUIAccount[]; - selectedAccountIDs: string[]; - onChange: (value: string[]) => void; -}; - -export function AccountMultiSelect({ - accounts, - selectedAccountIDs, - onChange, -}: AccountMultiSelectProps) { - return ( - - {accounts.map((account) => ( - -
    - -
    -
    - ))} -
    - ); -} - -export function AccountMultiSelectWithControls({ - selectedAccountIDs: selectedAccountsFromProps, - accounts, - onChange: onChangeFromProps, -}: AccountMultiSelectProps) { - const [selectedAccountIds, setSelectedAccountsIds] = useState(selectedAccountsFromProps); - const onChange = (value: string[]) => { - setSelectedAccountsIds(value); - onChangeFromProps(value); - }; - return ( -
    - - - {accounts.length > 1 ? ( -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx b/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx deleted file mode 100644 index c4883135397bb..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type ZkLoginProvider } from '_src/background/accounts/zklogin/providers'; -import { type Wallet } from '_src/shared/qredo-api'; -import { - createContext, - useCallback, - useContext, - useMemo, - useRef, - type MutableRefObject, - type ReactNode, -} from 'react'; - -export type AccountsFormValues = - | { type: 'zkLogin'; provider: ZkLoginProvider } - | { type: 'new-mnemonic' } - | { type: 'import-mnemonic'; entropy: string } - | { type: 'mnemonic-derived'; sourceID: string } - | { type: 'imported'; keyPair: string } - | { - type: 'ledger'; - accounts: { publicKey: string; derivationPath: string; address: string }[]; - } - | { type: 'qredo'; accounts: Wallet[]; qredoID: string } - | null; - -type AccountsFormContextType = [ - MutableRefObject, - (values: AccountsFormValues) => void, -]; - -const AccountsFormContext = createContext(null); - -export const AccountsFormProvider = ({ children }: { children: ReactNode }) => { - const valuesRef = useRef(null); - const setter = useCallback((values: AccountsFormValues) => { - valuesRef.current = values; - }, []); - const value = useMemo(() => [valuesRef, setter] as AccountsFormContextType, [setter]); - return {children}; -}; - -// a simple hook that allows form values to be shared between forms when setting up an account -// for the first time, or when importing an existing account. -export const useAccountsFormContext = () => { - const context = useContext(AccountsFormContext); - if (!context) { - throw new Error('useAccountsFormContext must be used within the AccountsFormProvider'); - } - return context; -}; diff --git a/apps/wallet/src/ui/app/components/accounts/AccountsList.tsx b/apps/wallet/src/ui/app/components/accounts/AccountsList.tsx deleted file mode 100644 index 88e480ba004ec..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AccountsList.tsx +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { Collapsible } from '_src/ui/app/shared/collapse'; -import { Filter16, Plus12 } from '@mysten/icons'; -import * as ToggleGroup from '@radix-ui/react-toggle-group'; -import cn from 'clsx'; -import { useMemo, useState } from 'react'; - -import { getAccountBackgroundByType } from '../../helpers/accounts'; -import { useAccountGroups } from '../../hooks/useAccountGroups'; -import { useActiveAccount } from '../../hooks/useActiveAccount'; -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { Heading } from '../../shared/heading'; -import { AccountListItem } from './AccountListItem'; -import { FooterLink } from './FooterLink'; - -export function AccountsList() { - const accountGroups = useAccountGroups(); - const accounts = accountGroups.list(); - const activeAccount = useActiveAccount(); - const backgroundClient = useBackgroundClient(); - const [isSwitchToAccountOpen, setIsSwitchToAccountOpen] = useState(false); - - const otherAccounts = useMemo( - () => accounts.filter((a) => a.id !== activeAccount?.id) || [], - [accounts, activeAccount?.id], - ); - - const handleSelectAccount = async (accountID: string) => { - const account = accounts?.find((a) => a.id === accountID); - if (!account) return; - if (accountID !== activeAccount?.id) { - ampli.switchedAccount({ - toAccountType: account.type, - }); - await backgroundClient.selectAccount(accountID); - setIsSwitchToAccountOpen(false); - } - }; - if (!accounts || !activeAccount) return null; - - return ( -
    - - Accounts - - - - <> - - -
    - -
    -
    -
    - - {otherAccounts.length ? ( - -
    - {otherAccounts.map((account) => { - return ( - -
    - -
    -
    - ); - })} -
    -
    - ) : null} - -
    - -
    - } to="/accounts/manage" text="Manage" /> - } to="/accounts/add-account" text="Add" /> -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/AutoLockSelector.tsx b/apps/wallet/src/ui/app/components/accounts/AutoLockSelector.tsx deleted file mode 100644 index 136e7c44e4c85..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/AutoLockSelector.tsx +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; -import { useFormContext } from 'react-hook-form'; -import { z } from 'zod'; - -import { CheckboxField } from '../../shared/forms/CheckboxField'; -import { Input } from '../../shared/forms/controls/Input'; -import FormField from '../../shared/forms/FormField'; -import { SelectField } from '../../shared/forms/SelectField'; - -const lockIntervals = [ - { id: 'day', label: 'Day' }, - { id: 'hour', label: 'Hour' }, - { id: 'minute', label: 'Minute' }, -]; -const lockIntervalsPlural = [ - { id: 'day', label: 'Days' }, - { id: 'hour', label: 'Hours' }, - { id: 'minute', label: 'Minutes' }, -]; - -export const zodSchema = z.object({ - autoLock: z - .object({ - enabled: z.boolean(), - timer: z.coerce.number().int('Only integer numbers allowed'), - interval: z.enum(['day', 'hour', 'minute']), - }) - .refine(({ enabled, timer }) => !enabled || timer > 0, { - message: 'Minimum of 1 minute is allowed', - path: ['timer'], - }), -}); - -type AutoLockSelectorProps = { - disabled?: boolean; -}; - -export function AutoLockSelector({ disabled }: AutoLockSelectorProps) { - const { register, watch, trigger } = useFormContext(); - const timer = watch('autoLock.timer'); - const timerEnabled = watch('autoLock.enabled'); - useEffect(() => { - const { unsubscribe } = watch((_, { name, type }) => { - if (name === 'autoLock.enabled' && type === 'change') { - trigger('autoLock.timer'); - } - }); - return unsubscribe; - }, [watch, trigger]); - return ( -
    - - -
    - - -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/EditableAccountName.tsx b/apps/wallet/src/ui/app/components/accounts/EditableAccountName.tsx deleted file mode 100644 index abe27022354c6..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/EditableAccountName.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useZodForm } from '@mysten/core'; -import { forwardRef, useRef, type ComponentProps } from 'react'; -import toast from 'react-hot-toast'; -import { z } from 'zod'; - -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { Form } from '../../shared/forms/Form'; - -type InputProps = Omit, 'className'>; - -export const Input = forwardRef((props, forwardedRef) => ( - -)); - -const formSchema = z.object({ - nickname: z.string().trim(), -}); - -export function EditableAccountName({ accountID, name }: { accountID: string; name: string }) { - const backgroundClient = useBackgroundClient(); - const form = useZodForm({ - mode: 'all', - schema: formSchema, - values: { - nickname: name, - }, - }); - const { register } = form; - const onSubmit = async ({ nickname }: { nickname: string }) => { - if (accountID) { - try { - await backgroundClient.setAccountNickname({ - id: accountID, - nickname: nickname || null, - }); - const activeElement = document.activeElement as HTMLElement; - activeElement?.blur(); - } catch (e) { - toast.error((e as Error).message || 'Failed to set nickname'); - } - } - }; - const { ref, ...inputFormData } = register('nickname'); - const inputRef = useRef(); - return ( -
    -
    - { - ref(instance); - inputRef.current = instance; - }} - onBlur={form.handleSubmit(onSubmit)} - onFocus={() => inputRef.current?.select()} - /> -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/FooterLink.tsx b/apps/wallet/src/ui/app/components/accounts/FooterLink.tsx deleted file mode 100644 index e576e4f3b04f4..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/FooterLink.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { forwardRef } from 'react'; - -import { Link, type LinkProps } from '../../shared/Link'; - -const FooterLink = forwardRef((props: LinkProps & { icon?: React.ReactNode }, forwardedRef) => { - return ( -
    - -
    - ); -}); - -export { FooterLink }; diff --git a/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx b/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx deleted file mode 100644 index b0fde71bf1caa..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { useZodForm } from '@mysten/core'; -import { type SubmitHandler } from 'react-hook-form'; -import { useNavigate } from 'react-router-dom'; -import { z } from 'zod'; - -import { privateKeyValidation } from '../../helpers/validation/privateKeyValidation'; -import { Form } from '../../shared/forms/Form'; -import { TextAreaField } from '../../shared/forms/TextAreaField'; - -const formSchema = z.object({ - privateKey: privateKeyValidation, -}); - -type FormValues = z.infer; - -type ImportPrivateKeyFormProps = { - onSubmit: SubmitHandler; -}; - -export function ImportPrivateKeyForm({ onSubmit }: ImportPrivateKeyFormProps) { - const form = useZodForm({ - mode: 'onTouched', - schema: formSchema, - }); - const { - register, - formState: { isSubmitting, isValid }, - } = form; - const navigate = useNavigate(); - return ( -
    - -
    -
    - - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/ImportRecoveryPhraseForm.tsx b/apps/wallet/src/ui/app/components/accounts/ImportRecoveryPhraseForm.tsx deleted file mode 100644 index 4dbfefb652ab1..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/ImportRecoveryPhraseForm.tsx +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { normalizeMnemonics, validateMnemonics } from '_src/shared/utils/bip39'; -import { PasswordInput } from '_src/ui/app/shared/forms/controls/PasswordInput'; -import { Text } from '_src/ui/app/shared/text'; -import { useZodForm } from '@mysten/core'; -import { type SubmitHandler } from 'react-hook-form'; -import { useNavigate } from 'react-router-dom'; -import { z } from 'zod'; - -import Alert from '../alert'; - -const RECOVERY_PHRASE_WORD_COUNT = 12; - -const formSchema = z.object({ - recoveryPhrase: z - .array(z.string().trim()) - .length(RECOVERY_PHRASE_WORD_COUNT) - .transform((recoveryPhrase) => normalizeMnemonics(recoveryPhrase.join(' ')).split(' ')) - .refine((recoveryPhrase) => validateMnemonics(recoveryPhrase.join(' ')), { - message: 'Recovery Passphrase is invalid', - }), -}); - -export type FormValues = z.infer; - -type ImportRecoveryPhraseFormProps = { - submitButtonText: string; - cancelButtonText?: string; - onSubmit: SubmitHandler; -}; - -export function ImportRecoveryPhraseForm({ - submitButtonText, - cancelButtonText, - onSubmit, -}: ImportRecoveryPhraseFormProps) { - const { - register, - formState: { errors, isSubmitting, isValid, touchedFields }, - handleSubmit, - setValue, - getValues, - trigger, - } = useZodForm({ - mode: 'all', - reValidateMode: 'onChange', - schema: formSchema, - defaultValues: { - recoveryPhrase: Array.from({ length: RECOVERY_PHRASE_WORD_COUNT }, () => ''), - }, - }); - const navigate = useNavigate(); - const recoveryPhrase = getValues('recoveryPhrase'); - - return ( -
    -
    - {recoveryPhrase.map((_, index) => { - const recoveryPhraseId = `recoveryPhrase.${index}` as const; - return ( - - ); - })} -
    -
    - {touchedFields.recoveryPhrase && errors.recoveryPhrase && ( - {errors.recoveryPhrase.message} - )} -
    - {cancelButtonText ? ( -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/LockUnlockButton.tsx b/apps/wallet/src/ui/app/components/accounts/LockUnlockButton.tsx deleted file mode 100644 index 4a85bebf05533..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/LockUnlockButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { LockLocked16, LockUnlocked16 } from '@mysten/icons'; -import { type ComponentPropsWithoutRef } from 'react'; - -import { Tooltip } from '../../shared/tooltip'; -import LoadingIndicator from '../loading/LoadingIndicator'; - -interface LockUnlockButtonProps extends ComponentPropsWithoutRef<'button'> { - isLocked: boolean; - isLoading: boolean; -} - -export function LockUnlockButton({ isLocked, onClick, isLoading }: LockUnlockButtonProps) { - return ( - - - - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/NicknameDialog.tsx b/apps/wallet/src/ui/app/components/accounts/NicknameDialog.tsx deleted file mode 100644 index 515d07b7c1652..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/NicknameDialog.tsx +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '_src/ui/app/shared/Dialog'; -import { useZodForm } from '@mysten/core'; -import { useState } from 'react'; -import toast from 'react-hot-toast'; -import { z } from 'zod'; - -import { useAccounts } from '../../hooks/useAccounts'; -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { Button } from '../../shared/ButtonUI'; -import { Form } from '../../shared/forms/Form'; -import { TextField } from '../../shared/forms/TextField'; - -const formSchema = z.object({ - nickname: z.string().trim(), -}); - -interface NicknameDialogProps { - accountID: string; - trigger: JSX.Element; -} - -export function NicknameDialog({ accountID, trigger }: NicknameDialogProps) { - const [open, setOpen] = useState(false); - const backgroundClient = useBackgroundClient(); - const { data: accounts } = useAccounts(); - const account = accounts?.find((account) => account.id === accountID); - - const form = useZodForm({ - mode: 'all', - schema: formSchema, - defaultValues: { - nickname: account?.nickname ?? '', - }, - }); - const { - register, - formState: { isSubmitting, isValid }, - } = form; - - const onSubmit = async ({ nickname }: { nickname: string }) => { - if (account && accountID) { - try { - await backgroundClient.setAccountNickname({ - id: accountID, - nickname: nickname || null, - }); - setOpen(false); - } catch (e) { - toast.error((e as Error).message || 'Failed to set nickname'); - } - } - }; - - return ( - - {trigger} - e.preventDefault()}> - - Account Nickname - - Enter your account password to unlock your account - - -
    - -
    -
    - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/PasswordInputDialog.tsx b/apps/wallet/src/ui/app/components/accounts/PasswordInputDialog.tsx deleted file mode 100644 index c9daa95d5ce00..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/PasswordInputDialog.tsx +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '_src/ui/app/shared/Dialog'; -import { useZodForm } from '@mysten/core'; -import { useState } from 'react'; -import { toast } from 'react-hot-toast'; -import { v4 as uuidV4 } from 'uuid'; -import { z } from 'zod'; - -import { useAccountSources } from '../../hooks/useAccountSources'; -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { PasswordInput } from '../../shared/forms/controls/PasswordInput'; -import { Form } from '../../shared/forms/Form'; -import FormField from '../../shared/forms/FormField'; -import { Link } from '../../shared/Link'; - -const formSchema = z.object({ - password: z.string().nonempty('Required'), -}); - -export type PasswordModalDialogProps = { - onClose: () => void; - open: boolean; - showForgotPassword?: boolean; - title: string; - description: string; - confirmText: string; - cancelText: string; - onSubmit: (password: string) => Promise | void; - verify?: boolean; -}; - -export function PasswordModalDialog({ - onClose, - onSubmit, - open, - verify, - showForgotPassword, - title, - description, - confirmText, - cancelText, -}: PasswordModalDialogProps) { - const form = useZodForm({ - mode: 'all', - schema: formSchema, - defaultValues: { - password: '', - }, - }); - const { - register, - setError, - reset, - formState: { isSubmitting, isValid }, - } = form; - const backgroundService = useBackgroundClient(); - const [formID] = useState(() => uuidV4()); - const { data: allAccountsSources } = useAccountSources(); - const hasMnemonicAccountsSources = - allAccountsSources?.some(({ type }) => type === 'mnemonic') || false; - return ( - - e.preventDefault()}> - - {title} - - {description} - - -
    { - try { - if (verify) { - await backgroundService.verifyPassword({ password }); - } - try { - await onSubmit(password); - reset(); - } catch (e) { - toast.error((e as Error).message || 'Something went wrong'); - } - } catch (e) { - setError( - 'password', - { message: (e as Error).message || 'Wrong password' }, - { shouldFocus: true }, - ); - } - }} - > - - - - -
    - -
    -
    -
    - {showForgotPassword && hasMnemonicAccountsSources ? ( - - ) : null} -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/ProtectAccountForm.tsx b/apps/wallet/src/ui/app/components/accounts/ProtectAccountForm.tsx deleted file mode 100644 index 65bc8f99896dc..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/ProtectAccountForm.tsx +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { ToS_LINK } from '_src/shared/constants'; -import { useZodForm } from '@mysten/core'; -import { useEffect } from 'react'; -import { type SubmitHandler } from 'react-hook-form'; -import { useNavigate } from 'react-router-dom'; -import { z } from 'zod'; -import zxcvbn from 'zxcvbn'; - -import { parseAutoLock, useAutoLockMinutes } from '../../hooks/useAutoLockMinutes'; -import { CheckboxField } from '../../shared/forms/CheckboxField'; -import { Form } from '../../shared/forms/Form'; -import { TextField } from '../../shared/forms/TextField'; -import { Link } from '../../shared/Link'; -import { AutoLockSelector, zodSchema } from './AutoLockSelector'; - -function addDot(str: string | undefined) { - if (str && !str.endsWith('.')) { - return `${str}.`; - } - return str; -} - -const formSchema = z - .object({ - password: z - .object({ - input: z - .string() - .nonempty('Required') - .superRefine((val, ctx) => { - const { - score, - feedback: { warning, suggestions }, - } = zxcvbn(val); - if (score <= 2) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `${addDot(warning) || 'Password is not strong enough.'}${ - suggestions ? ` ${suggestions.join(' ')}` : '' - }`, - }); - } - }), - confirmation: z.string().nonempty('Required'), - }) - .refine(({ input, confirmation }) => input && confirmation && input === confirmation, { - path: ['confirmation'], - message: "Passwords don't match", - }), - acceptedTos: z.literal(true, { - errorMap: () => ({ message: 'Please accept Terms of Service to continue' }), - }), - }) - .merge(zodSchema); - -export type FormValues = z.infer; - -type ProtectAccountFormProps = { - submitButtonText: string; - cancelButtonText?: string; - onSubmit: SubmitHandler; - displayToS?: boolean; -}; - -export function ProtectAccountForm({ - submitButtonText, - cancelButtonText, - onSubmit, - displayToS, -}: ProtectAccountFormProps) { - const autoLock = useAutoLockMinutes(); - const form = useZodForm({ - mode: 'all', - schema: formSchema, - values: { - password: { input: '', confirmation: '' }, - acceptedTos: !!displayToS, - autoLock: parseAutoLock(autoLock.data || null), - }, - }); - const { - watch, - register, - formState: { isSubmitting, isValid }, - trigger, - getValues, - } = form; - const navigate = useNavigate(); - useEffect(() => { - const { unsubscribe } = watch((_, { name, type }) => { - if (name === 'password.input' && type === 'change' && getValues('password.confirmation')) { - trigger('password.confirmation'); - } - }); - return unsubscribe; - }, [watch, trigger, getValues]); - return ( -
    - - - -
    -
    - {displayToS ? null : ( - - I read and agreed to the{' '} - - - -
    - } - /> - )} -
    - {cancelButtonText ? ( -
    -
    - - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/RecoverAccountsGroup.tsx b/apps/wallet/src/ui/app/components/accounts/RecoverAccountsGroup.tsx deleted file mode 100644 index 1c58ba2f66937..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/RecoverAccountsGroup.tsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { CheckFill16 } from '@mysten/icons'; - -import { Link } from '../../shared/Link'; -import { Text } from '../../shared/text'; -import { Tooltip } from '../../shared/tooltip'; -import { AccountListItem } from './AccountListItem'; - -export type RecoverAccountsGroupProps = { - title: string; - accounts: SerializedUIAccount[]; - showRecover?: boolean; - onRecover?: () => void; - recoverDone?: boolean; -}; - -export function RecoverAccountsGroup({ - title, - accounts, - showRecover, - onRecover, - recoverDone, -}: RecoverAccountsGroupProps) { - return ( -
    -
    - - {title} - -
    -
    - {showRecover && !recoverDone ? ( - - ) : null} - {recoverDone ? ( - - - - ) : null} -
    -
    - {accounts.map((anAccount) => ( - - ))} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/accounts/UnlockAccountButton.tsx b/apps/wallet/src/ui/app/components/accounts/UnlockAccountButton.tsx deleted file mode 100644 index a2787bbf447b8..0000000000000 --- a/apps/wallet/src/ui/app/components/accounts/UnlockAccountButton.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { isZkLoginAccountSerializedUI } from '_src/background/accounts/zklogin/ZkLoginAccount'; - -import { Button } from '../../shared/ButtonUI'; -import { SocialButton } from '../../shared/SocialButton'; -import { useUnlockAccount } from './UnlockAccountContext'; - -export type UnlockAccountButtonProps = { - account: SerializedUIAccount; - title?: string; -}; -export function UnlockAccountButton({ - account, - title = 'Unlock Account', -}: UnlockAccountButtonProps) { - const { isPasswordUnlockable } = account; - const { unlockAccount, isPending } = useUnlockAccount(); - - if (isPasswordUnlockable) { - return -
    -
    -
    - ); - })} - - ); -} diff --git a/apps/wallet/src/ui/app/components/buynlarge/close.svg b/apps/wallet/src/ui/app/components/buynlarge/close.svg deleted file mode 100644 index 1aa2be1cfd6f9..0000000000000 --- a/apps/wallet/src/ui/app/components/buynlarge/close.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/wallet/src/ui/app/components/buynlarge/useBuyNLargeAssets.ts b/apps/wallet/src/ui/app/components/buynlarge/useBuyNLargeAssets.ts deleted file mode 100644 index e1976e8752ce8..0000000000000 --- a/apps/wallet/src/ui/app/components/buynlarge/useBuyNLargeAssets.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClientQuery } from '@mysten/dapp-kit'; - -import { useActiveAddress } from '../../hooks'; -import { useConfig } from './useConfig'; - -export function useBuyNLargeAssets() { - const config = useConfig(); - const address = useActiveAddress(); - const { data } = useSuiClientQuery( - 'getOwnedObjects', - { - owner: address ?? '', - filter: { MatchAny: config.map(({ objectType }) => ({ StructType: objectType ?? '' })) }, - options: { showDisplay: true, showType: true }, - }, - { - enabled: !!address && config.some(({ enabled }) => enabled), - }, - ); - - return config - ?.map((item) => { - if (!item.enabled) return null; - return { - ...item, - asset: data?.data.find((x) => x.data?.type === item.objectType), - }; - }) - .filter((x) => !!x); -} diff --git a/apps/wallet/src/ui/app/components/buynlarge/useConfig.ts b/apps/wallet/src/ui/app/components/buynlarge/useConfig.ts deleted file mode 100644 index af8b75ab9ce37..0000000000000 --- a/apps/wallet/src/ui/app/components/buynlarge/useConfig.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useFeatureValue } from '@growthbook/growthbook-react'; - -type BuyNLargeConfig = { - enabled: boolean; - objectType: string; - sheetTitle: string; - sheetDescription: string; - homeDescription: string; - homeImage: string; - backgroundColor: string; -}; - -export function useConfig() { - return useFeatureValue('buynlargev2', []); -} diff --git a/apps/wallet/src/ui/app/components/coin-icon/index.tsx b/apps/wallet/src/ui/app/components/coin-icon/index.tsx deleted file mode 100644 index d164aacb86ea1..0000000000000 --- a/apps/wallet/src/ui/app/components/coin-icon/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ImageIcon } from '_app/shared/image-icon'; -import { useCoinMetadata } from '@mysten/core'; -import { Sui, Unstaked } from '@mysten/icons'; -import { normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { cva, type VariantProps } from 'class-variance-authority'; - -import { useCoinMetadataOverrides } from '../../hooks/useCoinMetadataOverride'; - -const imageStyle = cva(['rounded-full flex'], { - variants: { - size: { - sm: 'w-6 h-6', - md: 'w-7.5 h-7.5', - lg: 'md:w-10 md:h-10 w-8 h-8', - xl: 'md:w-31.5 md:h-31.5 w-16 h-16 ', - }, - fill: { - sui: 'bg-sui', - suiPrimary2023: 'bg-sui-primaryBlue2023', - }, - }, - defaultVariants: { - size: 'md', - fill: 'suiPrimary2023', - }, -}); - -function SuiCoin() { - return ( - - ); -} - -type NonSuiCoinProps = { - coinType: string; -}; - -function NonSuiCoin({ coinType }: NonSuiCoinProps) { - const { data: coinMeta } = useCoinMetadata(coinType); - const coinMetadataOverrides = useCoinMetadataOverrides(); - - return ( -
    - {coinMeta?.iconUrl ? ( - - ) : ( - - )} -
    - ); -} - -export interface CoinIconProps extends VariantProps { - coinType: string; -} - -export function CoinIcon({ coinType, ...styleProps }: CoinIconProps) { - const isSui = coinType - ? normalizeStructTag(coinType) === normalizeStructTag(SUI_TYPE_ARG) - : false; - - return ( -
    - {isSui ? : } -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/error-boundary/index.tsx b/apps/wallet/src/ui/app/components/error-boundary/index.tsx deleted file mode 100644 index 01673e551b301..0000000000000 --- a/apps/wallet/src/ui/app/components/error-boundary/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Alert from '_components/alert'; -import type { ReactNode } from 'react'; -import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'; -import type { FallbackProps } from 'react-error-boundary'; -import { useLocation } from 'react-router-dom'; - -function Fallback({ error }: FallbackProps) { - return ( -
    - -
    Something went wrong
    -
    {error.message}
    -
    -
    - ); -} - -export type ErrorBoundaryProps = { - children: ReactNode | ReactNode[]; -}; - -export function ErrorBoundary({ children }: ErrorBoundaryProps) { - const location = useLocation(); - return ( - - {children} - - ); -} diff --git a/apps/wallet/src/ui/app/components/explorer-link/Explorer.ts b/apps/wallet/src/ui/app/components/explorer-link/Explorer.ts deleted file mode 100644 index 1576968d4d5d3..0000000000000 --- a/apps/wallet/src/ui/app/components/explorer-link/Explorer.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { DEFAULT_API_ENV } from '_app/ApiProvider'; -import { getUrlWithDeviceId } from '_src/shared/analytics/amplitude'; -import { API_ENV } from '_src/shared/api-env'; - -const API_ENV_TO_EXPLORER_ENV: Record = { - [API_ENV.local]: 'local', - [API_ENV.devNet]: 'devnet', - [API_ENV.testNet]: 'testnet', - [API_ENV.mainnet]: 'mainnet', - [API_ENV.customRPC]: '', -}; - -const EXPLORER_LINK = 'https://suiexplorer.com/'; - -//TODO - this is a temporary solution, we should have a better way to get the explorer url -function getExplorerUrl(path: string, apiEnv: API_ENV = DEFAULT_API_ENV, customRPC: string) { - const explorerEnv = apiEnv === 'customRPC' ? customRPC : API_ENV_TO_EXPLORER_ENV[apiEnv]; - - const url = getUrlWithDeviceId(new URL(path, EXPLORER_LINK)); - if (explorerEnv) { - url.searchParams.append('network', explorerEnv); - } - - return url.href; -} - -export function getObjectUrl( - objectID: string, - apiEnv: API_ENV, - customRPC: string, - moduleName?: string | null, -) { - return getExplorerUrl( - `/object/${objectID}${moduleName ? `?module=${moduleName}` : ''}`, - apiEnv, - customRPC, - ); -} - -export function getTransactionUrl(txDigest: string, apiEnv: API_ENV, customRPC: string) { - return getExplorerUrl(`/txblock/${encodeURIComponent(txDigest)}`, apiEnv, customRPC); -} - -export function getAddressUrl(address: string, apiEnv: API_ENV, customRPC: string) { - return getExplorerUrl(`/address/${address}`, apiEnv, customRPC); -} - -export function getValidatorUrl(address: string, apiEnv: API_ENV, customRPC: string) { - return getExplorerUrl(`/validator/${address}`, apiEnv, customRPC); -} diff --git a/apps/wallet/src/ui/app/components/explorer-link/ExplorerLink.module.scss b/apps/wallet/src/ui/app/components/explorer-link/ExplorerLink.module.scss deleted file mode 100644 index db3c6ada1cb89..0000000000000 --- a/apps/wallet/src/ui/app/components/explorer-link/ExplorerLink.module.scss +++ /dev/null @@ -1,5 +0,0 @@ -.explorer-icon { - i { - line-height: 13px; - } -} diff --git a/apps/wallet/src/ui/app/components/explorer-link/ExplorerLinkType.ts b/apps/wallet/src/ui/app/components/explorer-link/ExplorerLinkType.ts deleted file mode 100644 index 7d83b4bdb14e1..0000000000000 --- a/apps/wallet/src/ui/app/components/explorer-link/ExplorerLinkType.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export enum ExplorerLinkType { - address = 'address', - object = 'object', - transaction = 'transaction', - validator = 'validator', -} diff --git a/apps/wallet/src/ui/app/components/explorer-link/index.tsx b/apps/wallet/src/ui/app/components/explorer-link/index.tsx deleted file mode 100644 index a1f9244e5c4dd..0000000000000 --- a/apps/wallet/src/ui/app/components/explorer-link/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import ExternalLink from '_components/external-link'; -import { ArrowUpRight16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import type { ReactNode } from 'react'; - -import { useExplorerLink, type ExplorerLinkConfig } from '../../hooks/useExplorerLink'; -import { Text } from '../../shared/text'; -import st from './ExplorerLink.module.scss'; -import { ExplorerLinkType } from './ExplorerLinkType'; - -export type ExplorerLinkProps = ExplorerLinkConfig & { - track?: boolean; - children?: ReactNode; - className?: string; - title?: string; - showIcon?: boolean; -}; - -function ExplorerLink({ - track, - children, - className, - title, - showIcon, - ...linkConfig -}: ExplorerLinkProps) { - const explorerHref = useExplorerLink(linkConfig); - if (!explorerHref) { - return null; - } - - return ( - - <> - {children} {showIcon && } - - - ); -} - -export function AddressLink({ address }: { address: string }) { - return ( - - - {formatAddress(address)} - - - ); -} - -export default ExplorerLink; diff --git a/apps/wallet/src/ui/app/components/external-link/index.tsx b/apps/wallet/src/ui/app/components/external-link/index.tsx deleted file mode 100644 index 396d4b8eb0624..0000000000000 --- a/apps/wallet/src/ui/app/components/external-link/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { memo } from 'react'; -import type { ReactNode } from 'react'; - -export type ExternalLinkProps = { - href: string; - className?: string; - children: ReactNode; - title?: string; - onClick?(): void; -}; - -function ExternalLink({ href, className, children, title, onClick }: ExternalLinkProps) { - return ( - - {children} - - ); -} - -export default memo(ExternalLink); diff --git a/apps/wallet/src/ui/app/components/filters-tags/Filters.module.scss b/apps/wallet/src/ui/app/components/filters-tags/Filters.module.scss deleted file mode 100644 index 015b8d95c53bd..0000000000000 --- a/apps/wallet/src/ui/app/components/filters-tags/Filters.module.scss +++ /dev/null @@ -1,38 +0,0 @@ -@use '_variables' as v; -@use '_utils'; -@use '_values' as values; -@use '_values/colors'; - -.filter-tags { - display: flex; - gap: 8px; - overflow-x: auto; - - &::-webkit-scrollbar { - width: 8px; - } - - &::-webkit-scrollbar-thumb { - background-color: transparent; - } - - .filter { - @include utils.typography('Primary/BodySmall-SB'); - - height: 25px; - background: colors.$white; - color: colors.$sui-blue-steel-dark; - padding: 6px 10px; - border: 1px solid colors.$sui-steel-blue; - border-radius: 16px; - text-decoration: none; - display: flex; - align-items: center; - - &.active { - background: colors.$hero-dark; - color: colors.$white; - border: 1px solid transparent; - } - } -} diff --git a/apps/wallet/src/ui/app/components/filters-tags/index.tsx b/apps/wallet/src/ui/app/components/filters-tags/index.tsx deleted file mode 100644 index 08dcc36251c9d..0000000000000 --- a/apps/wallet/src/ui/app/components/filters-tags/index.tsx +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import cl from 'clsx'; -import { memo, useEffect, useState } from 'react'; -import ReactDOM from 'react-dom'; -import { NavLink } from 'react-router-dom'; - -import st from './Filters.module.scss'; - -const ELEMENT_ID = '#sui-apps-filters'; - -// TODO: extend this interface to include params and functions for the filter tags -export interface Props { - name: string; - link: string; -} - -type Tags = { - tags: Props[]; - firstLastMargin?: boolean; - callback?: (tag: Props) => void; -}; - -function FiltersPortal({ tags, callback, firstLastMargin }: Tags) { - const [element, setElement] = useState(null); - - useEffect(() => { - const content = document.querySelector(ELEMENT_ID) as HTMLElement; - if (content) setElement(content); - }, []); - - return ( - <> - {element - ? ReactDOM.createPortal( -
    - {tags.map((tag) => { - return ( - { - return cl( - { [st.active]: isActive }, - st.filter, - firstLastMargin && 'first:ml-3 last:mr-3', - ); - }} - title={tag.name} - onClick={callback ? () => callback(tag) : undefined} - > - {tag.name} - - ); - })} -
    , - element, - ) - : null} - - ); -} - -export default memo(FiltersPortal); diff --git a/apps/wallet/src/ui/app/components/known-scam-overlay/index.tsx b/apps/wallet/src/ui/app/components/known-scam-overlay/index.tsx deleted file mode 100644 index e0652a7e93ba5..0000000000000 --- a/apps/wallet/src/ui/app/components/known-scam-overlay/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cx } from 'class-variance-authority'; - -import { Button } from '../../shared/ButtonUI'; -import { Heading } from '../../shared/heading'; -import { Portal } from '../../shared/Portal'; -import type { DappPreflightResponse } from './types'; -import WarningSvg from './warning.svg'; - -export type ScamOverlayProps = { - preflight: DappPreflightResponse; - onClickBack(): void; - onClickContinue(): void; -}; - -function Warning({ title, subtitle }: { title: string; subtitle: string }) { - return ( -
    - - {title || 'Malicious website'} - -
    -
    - {subtitle || - 'This website has been flagged for malicious behavior. To protect your wallet from potential threats, please return to safety.'} -
    -
    -
    - ); -} - -export function ScamOverlay({ preflight, onClickBack, onClickContinue }: ScamOverlayProps) { - const { block, warnings } = preflight; - - if (!block.enabled && !warnings?.length) return null; - - return ( - -
    - - - {!!block.enabled && } - - {warnings?.map(({ title, subtitle }, i) => { - // warnings list won't ever change, index key is fine - return ; - })} - -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/known-scam-overlay/types.ts b/apps/wallet/src/ui/app/components/known-scam-overlay/types.ts deleted file mode 100644 index 06166a8c27e0c..0000000000000 --- a/apps/wallet/src/ui/app/components/known-scam-overlay/types.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV } from '_src/shared/api-env'; - -export enum RequestType { - CONNECT = 'connect', - SIGN_TRANSACTION = 'sign-transaction', - SIGN_MESSAGE = 'sign-personal-message', -} - -export type DappPreflightResponse = { - block: { - enabled: boolean; - title: string; - subtitle: string; - }; - warnings?: { - title: string; - subtitle: string; - }[]; -}; - -export type Network = 'mainnet' | 'testnet' | 'devnet' | 'local'; - -export const API_ENV_TO_NETWORK: Record = { - [API_ENV.local]: 'local', - [API_ENV.devNet]: 'devnet', - [API_ENV.testNet]: 'testnet', - [API_ENV.mainnet]: 'mainnet', - [API_ENV.customRPC]: 'mainnet', // treat custom RPC as mainnet for now -}; - -export type DappPreflightRequest = { - network?: Network; - requestType: RequestType; - origin: string; - transactionBytes?: string; - message?: string; -}; diff --git a/apps/wallet/src/ui/app/components/known-scam-overlay/useDappPreflight.ts b/apps/wallet/src/ui/app/components/known-scam-overlay/useDappPreflight.ts deleted file mode 100644 index 02e556ec5a601..0000000000000 --- a/apps/wallet/src/ui/app/components/known-scam-overlay/useDappPreflight.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useAppsBackend } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { type Transaction } from '@mysten/sui/transactions'; -import { toBase64 } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; - -import { - RequestType, - type DappPreflightRequest, - type DappPreflightResponse, - type Network, -} from './types'; - -export function useDappPreflight({ - requestType, - origin, - transaction, - requestId, - network, -}: { - requestType: RequestType; - origin?: string; - transaction?: Transaction; - requestId: string; - network: Network; -}) { - const { request } = useAppsBackend(); - const client = useSuiClient(); - - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ['dapp-preflight', { requestId, requestType, origin }], - queryFn: async () => { - if (!origin) { - throw new Error('No origin provided'); - } - - const body: DappPreflightRequest = { - network, - requestType, - origin, - }; - - if (requestType === RequestType.SIGN_TRANSACTION && transaction) { - const transactionBytes = await transaction.build({ client }); - body.transactionBytes = toBase64(transactionBytes); - } - - return request( - 'v1/dapp-preflight', - {}, - { - method: 'POST', - body: JSON.stringify(body), - headers: { 'Content-Type': 'application/json' }, - }, - ); - }, - enabled: !!origin, - staleTime: 5 * 60 * 1000, - }); -} diff --git a/apps/wallet/src/ui/app/components/known-scam-overlay/useShowScamWarning.tsx b/apps/wallet/src/ui/app/components/known-scam-overlay/useShowScamWarning.tsx deleted file mode 100644 index cd7a0fc904438..0000000000000 --- a/apps/wallet/src/ui/app/components/known-scam-overlay/useShowScamWarning.tsx +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { type Transaction } from '@mysten/sui/transactions'; -import { useEffect } from 'react'; - -import { useAppSelector } from '../../hooks'; -import { API_ENV_TO_NETWORK, type RequestType } from './types'; -import { useDappPreflight } from './useDappPreflight'; - -export function useShowScamWarning({ - url, - requestType, - transaction, - requestId, -}: { - url?: URL; - requestType: RequestType; - transaction?: Transaction; - requestId: string; -}) { - const { apiEnv } = useAppSelector((state) => state.app); - const { data, isPending, isError } = useDappPreflight({ - requestType, - origin: url?.origin, - transaction, - requestId, - network: API_ENV_TO_NETWORK[apiEnv], - }); - - useEffect(() => { - if (data?.block.enabled && url?.hostname) { - ampli.interactedWithMaliciousDomain({ hostname: url.hostname }); - } - }, [data, url]); - - return { - data, - isPending, - isError, - }; -} diff --git a/apps/wallet/src/ui/app/components/known-scam-overlay/warning.svg b/apps/wallet/src/ui/app/components/known-scam-overlay/warning.svg deleted file mode 100644 index 944ae99d07e14..0000000000000 --- a/apps/wallet/src/ui/app/components/known-scam-overlay/warning.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/apps/wallet/src/ui/app/components/ledger/ConnectLedgerModal.tsx b/apps/wallet/src/ui/app/components/ledger/ConnectLedgerModal.tsx deleted file mode 100644 index 0a600c26c4bcc..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/ConnectLedgerModal.tsx +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { useSuiLedgerClient } from '_src/ui/app/components/ledger/SuiLedgerClientProvider'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from '_src/ui/app/shared/Dialog'; -import { Text } from '_src/ui/app/shared/text'; -import { useState } from 'react'; - -import { Link } from '../../shared/Link'; - -type ConnectLedgerModalProps = { - onClose: () => void; - onConfirm: () => void; - onError: (error: unknown) => void; -}; - -export function ConnectLedgerModal({ onClose, onConfirm, onError }: ConnectLedgerModalProps) { - const [isConnectingToLedger, setConnectingToLedger] = useState(false); - const { connectToLedger } = useSuiLedgerClient(); - - const onContinueClick = async () => { - try { - setConnectingToLedger(true); - await connectToLedger(true); - onConfirm(); - } catch (error) { - onError(error); - } finally { - setConnectingToLedger(false); - } - }; - - return ( - { - if (!open) { - onClose(); - } - }} - > - - - Connect Ledger Wallet - -
    -
    - -
    -
    - - Connect your ledger to your computer, unlock it, and launch the Sui app. Click - Continue when done. - -
    - - Need more help?  - - - ampli.viewedLedgerTutorial()} - text="View tutorial." - color="heroDark" - /> - -
    -
    -
    - -
    -
    -
    -
    -
    - ); -} - -// TODO: We should probably use a loader like @svgr/webpack so that we can provide SVG files -// and have them be automatically importable in React components. From playing around with -// this, there seems to be an issue where TypeScript bindings aren't correctly generated -// (see https://github.com/gregberge/svgr/pull/573) -function LedgerLogo() { - return ( - - - - ); -} diff --git a/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx b/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx deleted file mode 100644 index d90f7c585a401..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { LedgerAccountRow } from './LedgerAccountRow'; -import { type DerivedLedgerAccount } from './useDeriveLedgerAccounts'; - -export type SelectableLedgerAccount = DerivedLedgerAccount & { - isSelected: boolean; -}; - -type LedgerAccountListProps = { - accounts: SelectableLedgerAccount[]; - onAccountClick: (account: SelectableLedgerAccount) => void; -}; - -export function LedgerAccountList({ accounts, onAccountClick }: LedgerAccountListProps) { - return ( -
      - {accounts.map((account) => ( -
    • - -
    • - ))} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx b/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx deleted file mode 100644 index b494572f48a89..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin } from '@mysten/core'; -import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { CheckFill16 } from '@mysten/icons'; -import { formatAddress, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import cl from 'clsx'; - -import { useCoinsReFetchingConfig } from '../../hooks'; - -type LedgerAccountRowProps = { - isSelected: boolean; - address: string; -}; - -export function LedgerAccountRow({ isSelected, address }: LedgerAccountRowProps) { - const { staleTime, refetchInterval } = useCoinsReFetchingConfig(); - - const { data: coinBalance } = useSuiClientQuery( - 'getBalance', - { - coinType: SUI_TYPE_ARG, - owner: address, - }, - { - refetchInterval, - staleTime, - }, - ); - const domainName = useResolveSuiNSName(address); - - const [totalAmount, totalAmountSymbol] = useFormatCoin( - coinBalance?.totalBalance ?? 0, - SUI_TYPE_ARG, - ); - - return ( -
    - - - {domainName ?? formatAddress(address)} - -
    - - {totalAmount} {totalAmountSymbol} - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/ledger/SuiLedgerClientProvider.tsx b/apps/wallet/src/ui/app/components/ledger/SuiLedgerClientProvider.tsx deleted file mode 100644 index 40581567cdc05..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/SuiLedgerClientProvider.tsx +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import TransportWebHID from '@ledgerhq/hw-transport-webhid'; -import TransportWebUSB from '@ledgerhq/hw-transport-webusb'; -import SuiLedgerClient from '@mysten/ledgerjs-hw-app-sui'; -import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; - -import { - convertErrorToLedgerConnectionFailedError, - LedgerDeviceNotFoundError, - LedgerNoTransportMechanismError, -} from './ledgerErrors'; - -type SuiLedgerClientProviderProps = { - children: React.ReactNode; -}; - -type SuiLedgerClientContextValue = { - suiLedgerClient: SuiLedgerClient | undefined; - connectToLedger: (requestPermissionsFirst?: boolean) => Promise; -}; - -const SuiLedgerClientContext = createContext(undefined); - -export function SuiLedgerClientProvider({ children }: SuiLedgerClientProviderProps) { - const [suiLedgerClient, setSuiLedgerClient] = useState(); - const resetSuiLedgerClient = useCallback(async () => { - await suiLedgerClient?.transport.close(); - setSuiLedgerClient(undefined); - }, [suiLedgerClient]); - - useEffect(() => { - // NOTE: The disconnect event is fired when someone physically disconnects - // their Ledger device in addition to when user's exit out of an application - suiLedgerClient?.transport.on('disconnect', resetSuiLedgerClient); - return () => { - suiLedgerClient?.transport.off('disconnect', resetSuiLedgerClient); - }; - }, [resetSuiLedgerClient, suiLedgerClient?.transport]); - - const connectToLedger = useCallback( - async (requestPermissionsFirst = false) => { - // If we've already connected to a Ledger device, we need - // to close the connection before we try to re-connect - await resetSuiLedgerClient(); - - const ledgerTransport = requestPermissionsFirst - ? await requestLedgerConnection() - : await openLedgerConnection(); - const ledgerClient = new SuiLedgerClient(ledgerTransport); - setSuiLedgerClient(ledgerClient); - return ledgerClient; - }, - [resetSuiLedgerClient], - ); - const contextValue: SuiLedgerClientContextValue = useMemo(() => { - return { - suiLedgerClient, - connectToLedger, - }; - }, [connectToLedger, suiLedgerClient]); - - return ( - - {children} - - ); -} - -export function useSuiLedgerClient() { - const suiLedgerClientContext = useContext(SuiLedgerClientContext); - if (!suiLedgerClientContext) { - throw new Error('useSuiLedgerClient must be used within SuiLedgerClientContext'); - } - return suiLedgerClientContext; -} - -async function requestLedgerConnection() { - const ledgerTransportClass = await getLedgerTransportClass(); - try { - return await ledgerTransportClass.request(); - } catch (error) { - throw convertErrorToLedgerConnectionFailedError(error); - } -} - -async function openLedgerConnection() { - const ledgerTransportClass = await getLedgerTransportClass(); - let ledgerTransport: TransportWebHID | TransportWebUSB | null | undefined; - - try { - ledgerTransport = await ledgerTransportClass.openConnected(); - } catch (error) { - throw convertErrorToLedgerConnectionFailedError(error); - } - if (!ledgerTransport) { - throw new LedgerDeviceNotFoundError( - "The user doesn't have a Ledger device connected to their machine", - ); - } - return ledgerTransport; -} - -async function getLedgerTransportClass() { - if (await TransportWebHID.isSupported()) { - return TransportWebHID; - } else if (await TransportWebUSB.isSupported()) { - return TransportWebUSB; - } - throw new LedgerNoTransportMechanismError( - "There are no supported transport mechanisms to connect to the user's Ledger device", - ); -} diff --git a/apps/wallet/src/ui/app/components/ledger/ledgerErrors.ts b/apps/wallet/src/ui/app/components/ledger/ledgerErrors.ts deleted file mode 100644 index 5ce4338fada6e..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/ledgerErrors.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -interface LedgerTransportStatusError extends Error { - name: 'TransportStatusError'; - statusCode: number; -} - -export class LedgerConnectionFailedError extends Error { - constructor(message: string) { - super(message); - Object.setPrototypeOf(this, LedgerConnectionFailedError.prototype); - } -} - -export class LedgerNoTransportMechanismError extends Error { - constructor(message: string) { - super(message); - Object.setPrototypeOf(this, LedgerNoTransportMechanismError.prototype); - } -} - -export class LedgerDeviceNotFoundError extends Error { - constructor(message: string) { - super(message); - Object.setPrototypeOf(this, LedgerDeviceNotFoundError.prototype); - } -} - -// Connection methods from the Ledger transport libraries don't throw well-structured -// errors, so we can use this utility to form more explicit and structured errors -export function convertErrorToLedgerConnectionFailedError(error: unknown) { - const errorMessage = error instanceof Error ? error.message : String(error); - return new LedgerConnectionFailedError( - `Unable to connect to the user's Ledger device: ${errorMessage}`, - ); -} - -// When something goes wrong in the Sui application itself, a TransportStatusError is -// thrown. Unfortunately, @ledgerhq/errors doesn't expose this error in the form of a -// custom Error class. This makes identification of what went wrong less straightforward -export function isLedgerTransportStatusError(error: unknown): error is LedgerTransportStatusError { - return error instanceof Error && error.name === 'TransportStatusError'; -} diff --git a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts b/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts deleted file mode 100644 index c67a9e3216955..0000000000000 --- a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type LedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount'; -import type SuiLedgerClient from '@mysten/ledgerjs-hw-app-sui'; -import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519'; -import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; - -import { useSuiLedgerClient } from './SuiLedgerClientProvider'; - -export type DerivedLedgerAccount = Pick< - LedgerAccountSerializedUI, - 'address' | 'publicKey' | 'type' | 'derivationPath' ->; -type UseDeriveLedgerAccountOptions = { - numAccountsToDerive: number; -} & Pick, 'select'>; - -export function useDeriveLedgerAccounts(options: UseDeriveLedgerAccountOptions) { - const { numAccountsToDerive, ...useQueryOptions } = options; - const { suiLedgerClient } = useSuiLedgerClient(); - - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ['derive-ledger-accounts'], - queryFn: () => { - if (!suiLedgerClient) { - throw new Error("The Sui application isn't open on a connected Ledger device"); - } - return deriveAccountsFromLedger(suiLedgerClient, numAccountsToDerive); - }, - ...useQueryOptions, - gcTime: 0, - }); -} - -async function deriveAccountsFromLedger( - suiLedgerClient: SuiLedgerClient, - numAccountsToDerive: number, -) { - const ledgerAccounts: DerivedLedgerAccount[] = []; - const derivationPaths = getDerivationPathsForLedger(numAccountsToDerive); - - for (const derivationPath of derivationPaths) { - const publicKeyResult = await suiLedgerClient.getPublicKey(derivationPath); - const publicKey = new Ed25519PublicKey(publicKeyResult.publicKey); - const suiAddress = publicKey.toSuiAddress(); - ledgerAccounts.push({ - type: 'ledger', - address: suiAddress, - derivationPath, - publicKey: publicKey.toBase64(), - }); - } - - return ledgerAccounts; -} - -function getDerivationPathsForLedger(numDerivations: number) { - return Array.from({ - length: numDerivations, - }).map((_, index) => `m/44'/784'/${index}'/0'/0'`); -} diff --git a/apps/wallet/src/ui/app/components/loading/LoadingIndicator.tsx b/apps/wallet/src/ui/app/components/loading/LoadingIndicator.tsx deleted file mode 100644 index 519d7ee01f46d..0000000000000 --- a/apps/wallet/src/ui/app/components/loading/LoadingIndicator.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Spinner16 } from '@mysten/icons'; -import { cva, type VariantProps } from 'class-variance-authority'; - -const styles = cva('', { - variants: { - color: { - inherit: 'text-inherit', - sui: 'text-sui', - }, - }, -}); - -export type LoadingIndicatorProps = VariantProps; - -const LoadingIndicator = ({ color = 'sui' }: LoadingIndicatorProps) => { - return ; -}; - -export default LoadingIndicator; diff --git a/apps/wallet/src/ui/app/components/loading/index.tsx b/apps/wallet/src/ui/app/components/loading/index.tsx deleted file mode 100644 index f23df6cd747bf..0000000000000 --- a/apps/wallet/src/ui/app/components/loading/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { ReactNode } from 'react'; - -import LoadingIndicator, { type LoadingIndicatorProps } from './LoadingIndicator'; - -type LoadingProps = { - loading: boolean; - children: ReactNode | ReactNode[]; -} & LoadingIndicatorProps; - -const Loading = ({ loading, children, ...indicatorProps }: LoadingProps) => { - return loading ? ( -
    - -
    - ) : ( - <>{children} - ); -}; - -export default Loading; diff --git a/apps/wallet/src/ui/app/components/logo/index.tsx b/apps/wallet/src/ui/app/components/logo/index.tsx deleted file mode 100644 index fbdbad437f521..0000000000000 --- a/apps/wallet/src/ui/app/components/logo/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV } from '_src/shared/api-env'; -import { SuiCustomRpc, SuiDevnet, SuiLocal, SuiMainnet, SuiTestnet } from '@mysten/icons'; - -type LogoProps = { - networkName?: API_ENV; -}; - -const networkLogos = { - [API_ENV.mainnet]: SuiMainnet, - [API_ENV.devNet]: SuiDevnet, - [API_ENV.testNet]: SuiTestnet, - [API_ENV.local]: SuiLocal, - [API_ENV.customRPC]: SuiCustomRpc, -}; - -const Logo = ({ networkName }: LogoProps) => { - const LogoComponent = networkName ? networkLogos[networkName] : networkLogos[API_ENV.mainnet]; - - return ; -}; - -export default Logo; diff --git a/apps/wallet/src/ui/app/components/menu/button/MenuButton.module.scss b/apps/wallet/src/ui/app/components/menu/button/MenuButton.module.scss deleted file mode 100644 index f449580ba1148..0000000000000 --- a/apps/wallet/src/ui/app/components/menu/button/MenuButton.module.scss +++ /dev/null @@ -1,56 +0,0 @@ -@use '_variables' as v; - -$btn-width: 20px; -$btn-height: 14px; -$line-height: 2px; - -.button { - display: block; - background: none; - outline: none; - border: none; - width: $btn-width; - height: $btn-height; - position: relative; - cursor: pointer; - padding: 0; -} - -.line { - width: $btn-width; - height: $line-height; - background-color: v.use(v.$colors-menu-btn-color); - transition-property: opacity, transform, top; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - display: block; - position: absolute; - border-radius: 10px; - - &.line-1 { - top: 0; - } - - &.line-2 { - top: calc(50% - ($line-height / 2)); - } - - &.line-3 { - bottom: 0; - } -} - -.open { - > .line-1 { - top: calc(50% - ($line-height / 2)); - transform: rotate(45deg); - } - - > .line-2 { - transform: rotate(-45deg); - } - - > .line-3 { - opacity: 0; - } -} diff --git a/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx b/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx deleted file mode 100644 index bd187072dcd53..0000000000000 --- a/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ButtonOrLink } from '_src/ui/app/shared/utils/ButtonOrLink'; -import { HamburgerOpen24 as HamburgerOpenIcon, Settings24 as SettingsIcon } from '@mysten/icons'; -import { cx } from 'class-variance-authority'; - -import { useMenuIsOpen, useNextMenuUrl } from '../hooks'; - -export function WalletSettingsButton() { - const isOpen = useMenuIsOpen(); - const menuUrl = useNextMenuUrl(!isOpen, '/'); - const IconComponent = isOpen ? HamburgerOpenIcon : SettingsIcon; - - return ( - - - - ); -} diff --git a/apps/wallet/src/ui/app/components/menu/button/index.tsx b/apps/wallet/src/ui/app/components/menu/button/index.tsx deleted file mode 100644 index 57306fcf91c4a..0000000000000 --- a/apps/wallet/src/ui/app/components/menu/button/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMenuIsOpen, useNextMenuUrl } from '_components/menu/hooks'; -import cl from 'clsx'; -import { memo } from 'react'; -import { Link } from 'react-router-dom'; - -import st from './MenuButton.module.scss'; - -export type MenuButtonProps = { - className?: string; -}; - -function MenuButton({ className }: MenuButtonProps) { - const isOpen = useMenuIsOpen(); - const menuUrl = useNextMenuUrl(!isOpen, '/'); - return ( - - - - - - ); -} - -export default memo(MenuButton); diff --git a/apps/wallet/src/ui/app/components/menu/content/AutoLockAccounts.tsx b/apps/wallet/src/ui/app/components/menu/content/AutoLockAccounts.tsx deleted file mode 100644 index ad2d5aab3c824..0000000000000 --- a/apps/wallet/src/ui/app/components/menu/content/AutoLockAccounts.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useNextMenuUrl } from '_components/menu/hooks'; -import { - autoLockDataToMinutes, - parseAutoLock, - useAutoLockMinutes, -} from '_src/ui/app/hooks/useAutoLockMinutes'; -import { useAutoLockMinutesMutation } from '_src/ui/app/hooks/useAutoLockMinutesMutation'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { Form } from '_src/ui/app/shared/forms/Form'; -import { useZodForm } from '@mysten/core'; -import toast from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; - -import { AutoLockSelector, zodSchema } from '../../accounts/AutoLockSelector'; -import Loading from '../../loading'; -import Overlay from '../../overlay'; - -export function AutoLockAccounts() { - const mainMenuUrl = useNextMenuUrl(true, '/'); - const navigate = useNavigate(); - const autoLock = useAutoLockMinutes(); - const savedAutoLockData = parseAutoLock(autoLock.data || null); - const form = useZodForm({ - mode: 'all', - schema: zodSchema, - values: { - autoLock: savedAutoLockData, - }, - }); - const { - formState: { isSubmitting, isValid, isDirty }, - } = form; - const setAutoLockMutation = useAutoLockMinutesMutation(); - return ( - navigate(mainMenuUrl)} - > - -
    { - await setAutoLockMutation.mutateAsync( - { minutes: autoLockDataToMinutes(data.autoLock) }, - { - onSuccess: () => { - toast.success('Saved'); - }, - onError: (error) => { - toast.error((error as Error)?.message || 'Failed, something went wrong'); - }, - }, - ); - }} - > - -
    - - - ))} - - - {isCustomRpcInputVisible && ( - - - - )} - -
    - ); -}; - -export default NetworkSelector; diff --git a/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx b/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx deleted file mode 100644 index 39ee906e1a2c6..0000000000000 --- a/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { getKioskIdFromOwnerCap, hasDisplayData, useGetKioskContents } from '@mysten/core'; -import { type SuiObjectResponse } from '@mysten/sui/client'; -import cl from 'clsx'; - -import { useActiveAddress } from '../../hooks'; -import { Text } from '../../shared/text'; -import { NftImage, type NftImageProps } from './NftImage'; - -type KioskProps = { - object: SuiObjectResponse; - orientation?: 'vertical' | 'horizontal' | null; -} & Partial; - -// used to prevent the top image from overflowing the bottom of the container -// (clip-path is used instead of overflow-hidden as it can be animated) -const clipPath = '[clip-path:inset(0_0_7px_0_round_12px)] group-hover:[clip-path:inset(0_0_0_0)]'; - -const timing = - 'transition-all group-hover:delay-[0.25s] duration-300 ease-[cubic-bezier(0.68,-0.55,0.265,1.55)]'; -const cardStyles = [ - `scale-100 group-hover:scale-95 object-cover origin-bottom z-30 group-hover:translate-y-0 translate-y-2 group-hover:shadow-md`, - `scale-[0.95] group-hover:-rotate-6 group-hover:-translate-x-5 group-hover:-translate-y-2 z-20 translate-y-0 group-hover:shadow-md`, - `scale-[0.90] group-hover:rotate-6 group-hover:translate-x-5 group-hover:-translate-y-2 z-10 -translate-y-2 group-hover:shadow-xl`, -]; - -function getLabel(item?: SuiObjectResponse) { - if (!item) return; - const display = item.data?.display?.data; - return display?.name ?? display?.description ?? item.data?.objectId; -} - -export function Kiosk({ object, orientation, ...nftImageProps }: KioskProps) { - const address = useActiveAddress(); - const { data: kioskData, isPending } = useGetKioskContents(address); - - const kioskId = getKioskIdFromOwnerCap(object); - const kiosk = kioskData?.kiosks.get(kioskId!); - const itemsWithDisplay = kiosk?.items.filter((item) => hasDisplayData(item)) ?? []; - - const showCardStackAnimation = itemsWithDisplay.length > 1 && orientation !== 'horizontal'; - const imagesToDisplay = orientation !== 'horizontal' ? 3 : 1; - const items = kiosk?.items.slice(0, imagesToDisplay) ?? []; - - // get the label for the first item to show on hover - const displayName = getLabel(items[0]); - - if (isPending) return null; - - return ( -
    -
    - {itemsWithDisplay.length === 0 ? ( - - ) : ( - items.map((item, idx) => { - const display = item.data?.display?.data; - return ( -
    -
    - -
    -
    - ); - }) - )} -
    - {orientation !== 'horizontal' && ( -
    - {displayName ? ( -
    - - {displayName} - -
    - ) : null} - -
    - - {kiosk?.items.length} - -
    -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/nft-display/NftImage.tsx b/apps/wallet/src/ui/app/components/nft-display/NftImage.tsx deleted file mode 100644 index b1c109752783b..0000000000000 --- a/apps/wallet/src/ui/app/components/nft-display/NftImage.tsx +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Image32, LockLocked16, MediaPlay16 } from '@mysten/icons'; -import { cva } from 'class-variance-authority'; -import type { VariantProps } from 'class-variance-authority'; -import cl from 'clsx'; -import { useState } from 'react'; - -const nftImageStyles = cva('overflow-hidden bg-gray-40 relative', { - variants: { - animateHover: { - true: [ - 'ease-ease-out-cubic duration-400', - 'group-hover:shadow-blurXl group-hover:shadow-steel/50', - ], - }, - borderRadius: { - md: 'rounded-md', - xl: 'rounded-xl', - sm: 'rounded', - }, - size: { - xs: 'w-10 h-10', - sm: 'w-12 h-12', - md: 'w-24 h-24', - lg: 'w-36 h-36', - xl: 'w-50 h-50', - }, - }, - compoundVariants: [ - { - animateHover: true, - borderRadius: 'xl', - class: 'group-hover:rounded-md', - }, - ], - defaultVariants: { - borderRadius: 'md', - }, -}); - -export interface NftImageProps extends VariantProps { - src: string | null; - video?: string | null; - name: string | null; - title?: string; - showLabel?: boolean; - playable?: boolean; - className?: string; - isLocked?: boolean; -} - -export function NftImage({ - src, - name, - title, - showLabel, - animateHover, - borderRadius, - size, - video, - playable, - className, - isLocked, -}: NftImageProps) { - const [error, setError] = useState(false); - const imgCls = cl( - 'w-full h-full object-cover', - animateHover && 'group-hover:scale-110 duration-500 ease-ease-out-cubic', - className, - ); - const imgSrc = src ? src.replace(/^ipfs:\/\//, 'https://ipfs.io/ipfs/') : ''; - - return ( -
    - {video ? ( - playable ? ( -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/nft-display/index.tsx b/apps/wallet/src/ui/app/components/nft-display/index.tsx deleted file mode 100644 index bfbaee0e4e1c0..0000000000000 --- a/apps/wallet/src/ui/app/components/nft-display/index.tsx +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Heading } from '_app/shared/heading'; -import Loading from '_components/loading'; -import { NftImage, type NftImageProps } from '_components/nft-display/NftImage'; -import { useFileExtensionType, useGetNFTMeta } from '_hooks'; -import { isKioskOwnerToken, useGetObject } from '@mysten/core'; -import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { formatAddress } from '@mysten/sui/utils'; -import { cva } from 'class-variance-authority'; -import type { VariantProps } from 'class-variance-authority'; - -import { useResolveVideo } from '../../hooks/useResolveVideo'; -import { Text } from '../../shared/text'; -import { Kiosk } from './Kiosk'; - -const nftDisplayCardStyles = cva('flex flex-nowrap items-center h-full relative', { - variants: { - animateHover: { - true: 'group', - }, - wideView: { - true: 'bg-gray-40 p-2.5 rounded-lg gap-2.5 flex-row-reverse justify-between', - false: '', - }, - orientation: { - horizontal: 'flex truncate', - vertical: 'flex-col', - }, - }, - defaultVariants: { - wideView: false, - orientation: 'vertical', - }, -}); - -export interface NFTDisplayCardProps extends VariantProps { - objectId: string; - hideLabel?: boolean; - size: NftImageProps['size']; - borderRadius?: NftImageProps['borderRadius']; - playable?: boolean; - isLocked?: boolean; -} - -export function NFTDisplayCard({ - objectId, - hideLabel, - size, - wideView, - animateHover, - borderRadius = 'md', - playable, - orientation, - isLocked, -}: NFTDisplayCardProps) { - const { data: objectData } = useGetObject(objectId); - const { data: nftMeta, isPending } = useGetNFTMeta(objectId); - const nftName = nftMeta?.name || formatAddress(objectId); - const nftImageUrl = nftMeta?.imageUrl || ''; - const video = useResolveVideo(objectData); - const fileExtensionType = useFileExtensionType(nftImageUrl); - const kioskClient = useKioskClient(); - const isOwnerToken = isKioskOwnerToken(kioskClient.network, objectData); - const shouldShowLabel = !wideView && orientation !== 'horizontal'; - - return ( -
    - - {objectData?.data && isOwnerToken ? ( - - ) : ( - - )} - {wideView && ( -
    - - {nftName} - -
    - {nftImageUrl ? ( - `${fileExtensionType.name} ${fileExtensionType.type}` - ) : ( - NO MEDIA - )} -
    -
    - )} - - {orientation === 'horizontal' ? ( -
    {nftName}
    - ) : !isOwnerToken && !hideLabel ? ( -
    -
    - - {nftName} - -
    -
    - ) : null} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/number-input/index.tsx b/apps/wallet/src/ui/app/components/number-input/index.tsx deleted file mode 100644 index 69e8650f3691e..0000000000000 --- a/apps/wallet/src/ui/app/components/number-input/index.tsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { FieldProps } from 'formik'; -import { NumericFormat } from 'react-number-format'; - -export interface NumberInputProps extends FieldProps { - allowNegative: boolean; - className?: string; - placeholder?: string; - disabled?: boolean; - decimals?: boolean; - suffix?: string; - prefix?: string; - autoFocus?: boolean; - 'data-testid'?: string; -} - -function NumberInput({ - allowNegative, - className, - placeholder, - disabled: forcedDisabled, - decimals = false, - field: { onBlur, name, value }, - form: { isSubmitting, setFieldValue }, - prefix, - suffix, - autoFocus, - 'data-testid': testId, -}: NumberInputProps) { - const disabled = forcedDisabled !== undefined ? forcedDisabled : isSubmitting; - return ( - setFieldValue(name, values.value), - prefix, - suffix, - autoFocus, - }} - /> - ); -} - -export default NumberInput; diff --git a/apps/wallet/src/ui/app/components/overlay/Overlay.module.scss b/apps/wallet/src/ui/app/components/overlay/Overlay.module.scss deleted file mode 100644 index e29451e182210..0000000000000 --- a/apps/wallet/src/ui/app/components/overlay/Overlay.module.scss +++ /dev/null @@ -1,77 +0,0 @@ -@use '_variables' as v; -@use '_values' as val; -@use '_values/colors'; -@use '_utils'; - -.container { - background: rgba(42 54 69 / 50%); - display: flex; - flex-flow: column nowrap; - align-items: center; - backdrop-filter: blur(20px); - z-index: 9999; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - -.full-screen-container { - border-radius: 12px; - overflow: hidden; -} - -.header { - width: 100%; - height: 48px; - background-color: colors.$white; -} - -.content { - width: 100%; - padding: 20px; - overflow-y: auto; - overflow-x: hidden; - background: colors.$white; - border-radius: 0 0 20px 20px; - position: relative; -} - -.close-overlay { - display: flex; - width: 44px; - justify-content: center; - align-content: center; - margin: auto; - cursor: pointer; - background: transparent; - border: none; - - .close { - color: #e1f3ff; - font-size: 32px; - font-weight: 100; - } - - .sui-icons-close { - font-size: 25px; - } - - :hover { - color: colors.$white; - } -} - -.header-content { - @include utils.typography('stats/text-lg'); - - display: flex; - flex-flow: column nowrap; - justify-content: center; - align-items: center; - width: 100%; - height: 48px; - background-color: rgba(225 243 255 / 50%); - color: colors.$sui-dark-blue; -} diff --git a/apps/wallet/src/ui/app/components/overlay/index.tsx b/apps/wallet/src/ui/app/components/overlay/index.tsx deleted file mode 100644 index e0eef1d6e3c07..0000000000000 --- a/apps/wallet/src/ui/app/components/overlay/index.tsx +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { X32 } from '@mysten/icons'; -import cl from 'clsx'; -import { useCallback } from 'react'; -import type { ReactNode } from 'react'; - -import useAppSelector from '../../hooks/useAppSelector'; -import { AppType } from '../../redux/slices/app/AppType'; -import { Portal } from '../../shared/Portal'; -import st from './Overlay.module.scss'; - -type OverlayProps = { - title?: ReactNode; - children: ReactNode; - showModal: boolean; - closeOverlay?: () => void; - closeIcon?: ReactNode | null; - setShowModal?: (showModal: boolean) => void; - background?: 'bg-sui-lightest'; -}; - -function Overlay({ - title, - children, - showModal, - closeOverlay, - setShowModal, - closeIcon = , - background, -}: OverlayProps) { - const closeModal = useCallback( - (e: React.MouseEvent) => { - closeOverlay && closeOverlay(); - setShowModal && setShowModal(false); - }, - [closeOverlay, setShowModal], - ); - const appType = useAppSelector((state) => state.app.appType); - const isFullScreen = appType === AppType.fullscreen; - - return showModal ? ( - -
    - {title && ( -
    -
    - {title} -
    -
    - )} -
    - {children} -
    - -
    -
    - ) : null; -} - -export default Overlay; diff --git a/apps/wallet/src/ui/app/components/receipt-card/ReceiptCardBg.tsx b/apps/wallet/src/ui/app/components/receipt-card/ReceiptCardBg.tsx deleted file mode 100644 index a7e2ef579562f..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/ReceiptCardBg.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; -import type { ReactNode } from 'react'; - -// TODO: use a single svg and change background color instead of using multiple svgs -const backgroundStyles = cva( - [ - "p-5 pb-0 rounded-t-4lg flex flex-col item-center after:content-[''] after:w-[320px] after:h-5 after:ml-[-20px] after:top-4 after:-mt-6 after:relative divide-y divide-solid divide-steel/20 divide-x-0", - ], - { - variants: { - status: { - success: "bg-success-light after:bg-[url('_assets/images/receipt_bottom.svg')]", - failure: "bg-issue-light after:bg-[url('_assets/images/receipt_bottom_red.svg')]", - pending: "bg-warning-light after:bg-[url('_assets/images/receipt_bottom_yellow.svg')]", - }, - }, - }, -); - -export interface ReceiptCardBgProps extends VariantProps { - children: ReactNode; -} - -export function ReceiptCardBg({ children, ...styleProps }: ReceiptCardBgProps) { - return
    {children}
    ; -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/SponsoredTxnGasSummary.tsx b/apps/wallet/src/ui/app/components/receipt-card/SponsoredTxnGasSummary.tsx deleted file mode 100644 index a176200c7bc87..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/SponsoredTxnGasSummary.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { GAS_SYMBOL, GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin } from '@mysten/core'; - -import { TxnAddressLink } from './TxnAddressLink'; - -type SponsoredTxnGasSummaryProps = { - totalGas: number; - sponsor: string; -}; - -export function SponsoredTxnGasSummary({ totalGas, sponsor }: SponsoredTxnGasSummaryProps) { - const [sponsorTotalAmount, sponsorTotalAmountSymbol] = useFormatCoin(totalGas, GAS_TYPE_ARG); - - return ( -
    - - Gas Fees - -
    - - You Paid - - - 0 {GAS_SYMBOL} - -
    -
    - - Paid by Sponsor - - - {sponsorTotalAmount} {sponsorTotalAmountSymbol} - -
    -
    - - Sponsor - - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx b/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx deleted file mode 100644 index e660bb49d4b15..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ValidatorLogo } from '_app/staking/validators/ValidatorLogo'; -import { TxnAmount } from '_components/receipt-card/TxnAmount'; -import { - NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE, - NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS, -} from '_src/shared/constants'; -import { CountDownTimer } from '_src/ui/app/shared/countdown-timer'; -import { Text } from '_src/ui/app/shared/text'; -import { IconTooltip } from '_src/ui/app/shared/tooltip'; -import { - formatPercentageDisplay, - useGetTimeBeforeEpochNumber, - useGetValidatorsApy, -} from '@mysten/core'; -import type { SuiEvent } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -import { Card } from '../../shared/transaction-summary/Card'; - -type StakeTxnCardProps = { - event: SuiEvent; -}; - -// For Staked Transaction use moveEvent Field to get the validator address, delegation amount, epoch -export function StakeTxnCard({ event }: StakeTxnCardProps) { - const json = event.parsedJson as { amount: string; validator_address: string; epoch: string }; - const validatorAddress = json?.validator_address; - const stakedAmount = json?.amount; - const stakedEpoch = Number(json?.epoch || '0'); - - const { data: rollingAverageApys } = useGetValidatorsApy(); - - const { apy, isApyApproxZero } = rollingAverageApys?.[validatorAddress] ?? { - apy: null, - }; - // Reward will be available after 2 epochs - // TODO: Get epochStartTimestampMs/StartDate - // for staking epoch + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE - const startEarningRewardsEpoch = Number(stakedEpoch) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS; - - const redeemableRewardsEpoch = - Number(stakedEpoch) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE; - - const { data: timeBeforeStakeRewardsStarts } = - useGetTimeBeforeEpochNumber(startEarningRewardsEpoch); - - const { data: timeBeforeStakeRewardsRedeemable } = - useGetTimeBeforeEpochNumber(redeemableRewardsEpoch); - - return ( - -
    - {validatorAddress && ( -
    - -
    - )} - {stakedAmount && } -
    -
    -
    - - APY - - -
    - - {formatPercentageDisplay(apy, '--', isApyApproxZero)} - -
    -
    -
    -
    -
    - - {timeBeforeStakeRewardsStarts > 0 - ? 'Staking Rewards Start' - : 'Staking Rewards Started'} - -
    - - {timeBeforeStakeRewardsStarts > 0 ? ( - - ) : ( - - Epoch #{startEarningRewardsEpoch} - - )} -
    -
    -
    - - Staking Rewards Redeemable - -
    -
    - {timeBeforeStakeRewardsRedeemable > 0 ? ( - - ) : ( - - Epoch #{redeemableRewardsEpoch} - - )} -
    -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/StatusIcon.tsx b/apps/wallet/src/ui/app/components/receipt-card/StatusIcon.tsx deleted file mode 100644 index 4fa2ad89e4913..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/StatusIcon.tsx +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ThumbUpFill32 } from '@mysten/icons'; -import cl from 'clsx'; - -export function StatusIcon({ status }: { status: boolean }) { - return ( -
    -
    - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAddress.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAddress.tsx deleted file mode 100644 index 6a64743f68021..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAddress.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { Text } from '_src/ui/app/shared/text'; - -import { TxnAddressLink } from './TxnAddressLink'; - -type TxnAddressProps = { - address: string; - label: string; -}; - -export function TxnAddress({ address, label }: TxnAddressProps) { - const domainName = useResolveSuiNSName(address); - - return ( -
    - - {label} - -
    - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx deleted file mode 100644 index 0c91c1ec61e62..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import ExplorerLink from '_components/explorer-link'; -import { ExplorerLinkType } from '_components/explorer-link/ExplorerLinkType'; -import { formatAddress, isValidSuiNSName } from '@mysten/sui/utils'; - -type TxnAddressLinkProps = { - address: string; -}; - -export function TxnAddressLink({ address }: TxnAddressLinkProps) { - return ( - - {isValidSuiNSName(address) ? address : formatAddress(address)} - - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx deleted file mode 100644 index b646e7d55fefb..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Heading } from '_src/ui/app/shared/heading'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin } from '@mysten/core'; - -type TxnAmountProps = { - amount: string | number; - coinType: string; - label: string; - approximation?: boolean; -}; - -// dont show amount if it is 0 -// This happens when a user sends a transaction to self; -export function TxnAmount({ amount, coinType, label, approximation }: TxnAmountProps) { - const [formatAmount, symbol] = useFormatCoin(Math.abs(Number(amount)), coinType); - return Number(amount) !== 0 ? ( -
    - - {label} - -
    - - {approximation ? '~' : ''} - {formatAmount} - - - {symbol} - -
    -
    - ) : null; -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx deleted file mode 100644 index e8fc1b6b482c8..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin } from '@mysten/core'; -import type { GasCostSummary } from '@mysten/sui/client'; - -type TxnGasSummaryProps = { - gasSummary?: GasCostSummary; - totalGas: bigint; - transferAmount: bigint | null; -}; - -//TODO add gas breakdown -export function TxnGasSummary({ gasSummary, totalGas, transferAmount }: TxnGasSummaryProps) { - const [totalAmount, totalAmountSymbol] = useFormatCoin( - totalGas + (transferAmount || 0n), - GAS_TYPE_ARG, - ); - const [gas, symbol] = useFormatCoin(totalGas, GAS_TYPE_ARG); - - return ( -
    -
    - - Gas Fees - - - {gas} {symbol} - -
    - {transferAmount ? ( -
    - - Total Amount - - - {totalAmount} {totalAmountSymbol} - -
    - ) : null} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx b/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx deleted file mode 100644 index 14fee4c651a4f..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ValidatorLogo } from '_app/staking/validators/ValidatorLogo'; -import { TxnAmount } from '_components/receipt-card/TxnAmount'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin } from '@mysten/core'; -import type { SuiEvent } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -import { Card } from '../../shared/transaction-summary/Card'; - -type UnStakeTxnCardProps = { - event: SuiEvent; -}; - -export function UnStakeTxnCard({ event }: UnStakeTxnCardProps) { - const json = event.parsedJson as { - principal_amount?: number; - reward_amount?: number; - validator_address?: string; - }; - const principalAmount = json?.principal_amount || 0; - const rewardAmount = json?.reward_amount || 0; - const validatorAddress = json?.validator_address; - const totalAmount = Number(principalAmount) + Number(rewardAmount); - const [formatPrinciple, symbol] = useFormatCoin(principalAmount, SUI_TYPE_ARG); - const [formatRewards] = useFormatCoin(rewardAmount || 0, SUI_TYPE_ARG); - - return ( - -
    - {validatorAddress && ( -
    - -
    - )} - {totalAmount && } - -
    -
    - - Your SUI Stake - -
    - -
    - - {formatPrinciple} {symbol} - -
    -
    - -
    -
    - - Staking Rewards Earned - -
    - -
    - - {formatRewards} {symbol} - -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/receipt-card/index.tsx b/apps/wallet/src/ui/app/components/receipt-card/index.tsx deleted file mode 100644 index e0c78ff5c921d..0000000000000 --- a/apps/wallet/src/ui/app/components/receipt-card/index.tsx +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useRecognizedPackages } from '_src/ui/app/hooks/useRecognizedPackages'; -import { useTransactionSummary } from '@mysten/core'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; - -import { DateCard } from '../../shared/date-card'; -import { TransactionSummary } from '../../shared/transaction-summary'; -import { ExplorerLinkCard } from '../../shared/transaction-summary/cards/ExplorerLink'; -import { GasSummary } from '../../shared/transaction-summary/cards/GasSummary'; -import { StakeTxnCard } from './StakeTxnCard'; -import { StatusIcon } from './StatusIcon'; -import { UnStakeTxnCard } from './UnstakeTxnCard'; - -type ReceiptCardProps = { - txn: SuiTransactionBlockResponse; - activeAddress: string; -}; - -function TransactionStatus({ success, timestamp }: { success: boolean; timestamp?: string }) { - return ( -
    - - - {success ? 'Transaction Success' : 'Transaction Failed'} - - {timestamp && } -
    - ); -} - -export function ReceiptCard({ txn, activeAddress }: ReceiptCardProps) { - const { events } = txn; - const recognizedPackagesList = useRecognizedPackages(); - const summary = useTransactionSummary({ - transaction: txn, - currentAddress: activeAddress, - recognizedPackagesList, - }); - - if (!summary) return null; - - const stakedTxn = events?.find(({ type }) => type === '0x3::validator::StakingRequestEvent'); - - const unstakeTxn = events?.find(({ type }) => type === '0x3::validator::UnstakingRequestEvent'); - - // todo: re-using the existing staking cards for now - if (stakedTxn || unstakeTxn) - return ( -
    - -
    -
    -
    - {stakedTxn ? : null} - {unstakeTxn ? : null} - - -
    -
    -
    -
    - ); - - return ( -
    - - -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/sui-apps/Banner.tsx b/apps/wallet/src/ui/app/components/sui-apps/Banner.tsx deleted file mode 100644 index e7bd0bc026872..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/Banner.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { FEATURES } from '_src/shared/experimentation/features'; -import { useFeature } from '@growthbook/growthbook-react'; - -import ExternalLink from '../external-link'; - -export type BannerProps = { - enabled: boolean; - bannerUrl?: string; - imageUrl?: string; -}; - -export function AppsPageBanner() { - const AppsBannerConfig = useFeature(FEATURES.WALLET_APPS_BANNER_CONFIG); - - if (!AppsBannerConfig.value?.enabled) { - return null; - } - - return ( -
    - {AppsBannerConfig.value?.bannerUrl && ( - ampli.clickedBullsharkQuestsCta({ sourceFlow: 'Banner - Apps tab' })} - > - Apps Banner - - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/sui-apps/ConnectedAppsCard.tsx b/apps/wallet/src/ui/app/components/sui-apps/ConnectedAppsCard.tsx deleted file mode 100644 index 130e08963e765..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/ConnectedAppsCard.tsx +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Heading } from '_app/shared/heading'; -import { Text } from '_app/shared/text'; -import { useAppSelector } from '_hooks'; -import { FEATURES } from '_src/shared/experimentation/features'; -import { prepareLinkToCompare } from '_src/shared/utils'; -import { useFeature } from '@growthbook/growthbook-react'; -import { useEffect, useMemo } from 'react'; - -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { permissionsSelectors } from '../../redux/slices/permissions'; -import Loading from '../loading'; -import { SuiApp, type DAppEntry } from './SuiApp'; -import { SuiAppEmpty } from './SuiAppEmpty'; - -const emptyArray: DAppEntry[] = []; - -function ConnectedDapps() { - const backgroundClient = useBackgroundClient(); - useEffect(() => { - backgroundClient.sendGetPermissionRequests(); - }, [backgroundClient]); - const ecosystemApps = useFeature(FEATURES.WALLET_DAPPS).value ?? emptyArray; - const loading = useAppSelector(({ permissions }) => !permissions.initialized); - const allPermissions = useAppSelector(permissionsSelectors.selectAll); - const connectedApps = useMemo( - () => - allPermissions - .filter(({ allowed }) => allowed) - .map((aPermission) => { - const matchedEcosystemApp = ecosystemApps.find((anEcosystemApp) => { - const originAdj = prepareLinkToCompare(aPermission.origin); - const pageLinkAdj = aPermission.pagelink - ? prepareLinkToCompare(aPermission.pagelink) - : null; - const anEcosystemAppLinkAdj = prepareLinkToCompare(anEcosystemApp.link); - return originAdj === anEcosystemAppLinkAdj || pageLinkAdj === anEcosystemAppLinkAdj; - }); - let appNameFromOrigin = ''; - try { - appNameFromOrigin = new URL(aPermission.origin).hostname - .replace('www.', '') - .split('.')[0]; - } catch (e) { - // do nothing - } - return { - name: aPermission.name || appNameFromOrigin, - description: '', - icon: aPermission.favIcon || '', - link: aPermission.pagelink || aPermission.origin, - tags: [], - // override data from ecosystemApps - ...matchedEcosystemApp, - permissionID: aPermission.id, - }; - }), - [allPermissions, ecosystemApps], - ); - return ( - -
    - - Active Connections - -
    -
    - - Apps you have connected to through the Sui Wallet in this browser. - -
    - -
    - {connectedApps.length ? ( - connectedApps.map((app) => ) - ) : ( - <> - - - - )} -
    -
    - ); -} - -export default ConnectedDapps; diff --git a/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx b/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx deleted file mode 100644 index dd5511deb8f43..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Overlay from '_components/overlay'; -import { useAppSelector } from '_hooks'; -import { permissionsSelectors } from '_redux/slices/permissions'; -import { ampli } from '_src/shared/analytics/ampli'; -import { formatAddress } from '@mysten/sui/utils'; -import { useMutation } from '@tanstack/react-query'; -import { useEffect, useMemo, useState } from 'react'; -import { toast } from 'react-hot-toast'; - -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { Button } from '../../shared/ButtonUI'; -import { Text } from '../../shared/text'; -import { DAppInfoCard } from '../DAppInfoCard'; -import { DAppPermissionsList } from '../DAppPermissionsList'; -import { SummaryCard } from '../SummaryCard'; -import { WalletListSelect } from '../WalletListSelect'; -import { type DAppEntry } from './SuiApp'; - -export interface DisconnectAppProps extends Omit { - permissionID: string; - setShowDisconnectApp: (showModal: boolean) => void; -} - -function DisconnectApp({ - name, - icon, - link, - permissionID, - setShowDisconnectApp, -}: DisconnectAppProps) { - const [accountsToDisconnect, setAccountsToDisconnect] = useState([]); - const permission = useAppSelector((state) => - permissionsSelectors.selectById(state, permissionID), - ); - useEffect(() => { - if (permission && !permission.allowed) { - setShowDisconnectApp(false); - } - }, [permission, setShowDisconnectApp]); - const connectedAccounts = useMemo( - () => (permission?.allowed && permission.accounts) || [], - [permission], - ); - const backgroundClient = useBackgroundClient(); - const disconnectMutation = useMutation({ - mutationFn: async () => { - const origin = permission?.origin; - if (!origin) { - throw new Error('Failed, origin not found'); - } - - await backgroundClient.disconnectApp(origin, accountsToDisconnect); - await backgroundClient.sendGetPermissionRequests(); - ampli.disconnectedApplication({ - sourceFlow: 'Application page', - disconnectedAccounts: accountsToDisconnect.length || 1, - applicationName: permission.name, - applicationUrl: origin, - }); - }, - onSuccess: () => { - toast.success('Disconnected successfully'); - setShowDisconnectApp(false); - }, - onError: () => toast.error('Disconnect failed'), - }); - if (!permission) { - return null; - } - return ( - -
    - - } - /> - {connectedAccounts.length > 1 ? ( - - ) : ( - - {connectedAccounts[0] ? formatAddress(connectedAccounts[0]) : null} - - } - /> - )} -
    -
    -
    -
    - ); -} - -export default DisconnectApp; diff --git a/apps/wallet/src/ui/app/components/sui-apps/SuiApp.tsx b/apps/wallet/src/ui/app/components/sui-apps/SuiApp.tsx deleted file mode 100644 index 0d635ab73c0f9..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/SuiApp.tsx +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ImageIcon } from '_app/shared/image-icon'; -import ExternalLink from '_components/external-link'; -import { ampli } from '_src/shared/analytics/ampli'; -import { getDAppUrl } from '_src/shared/utils'; -import { Text } from '_src/ui/app/shared/text'; -import { useState } from 'react'; - -import DisconnectApp from './DisconnectApp'; - -export type DAppEntry = { - name: string; - description: string; - link: string; - icon: string; - tags: string[]; -}; -export type DisplayType = 'full' | 'card'; - -type CardViewProp = { - name: string; - link: string; - icon?: string; -}; - -function CardView({ name, link, icon }: CardViewProp) { - const appUrl = getDAppUrl(link); - const originLabel = appUrl.hostname; - return ( -
    -
    - -
    - -
    -
    - - {name} - -
    - - {originLabel} - -
    -
    - ); -} - -type ListViewProp = { - name: string; - icon?: string; - description: string; - tags?: string[]; -}; - -function ListView({ name, icon, description, tags }: ListViewProp) { - return ( -
    - -
    - - {name} - - - {description} - - {tags?.length && ( -
    - {tags?.map((tag) => ( -
    - - {tag} - -
    - ))} -
    - )} -
    -
    - ); -} - -export interface SuiAppProps { - name: string; - description: string; - link: string; - icon: string; - tags: string[]; - permissionID?: string; - displayType: DisplayType; - openAppSite?: boolean; -} - -export function SuiApp({ - name, - description, - link, - icon, - tags, - permissionID, - displayType, - openAppSite, -}: SuiAppProps) { - const [showDisconnectApp, setShowDisconnectApp] = useState(false); - const appUrl = getDAppUrl(link); - - if (permissionID && showDisconnectApp) { - return ( - - ); - } - - const AppDetails = - displayType === 'full' ? ( - - ) : ( - - ); - - if (permissionID && !openAppSite) { - return ( -
    setShowDisconnectApp(true)} - role="button" - > - {AppDetails} -
    - ); - } - - return ( - { - ampli.openedApplication({ applicationName: name }); - }} - > - {AppDetails} - - ); -} diff --git a/apps/wallet/src/ui/app/components/sui-apps/SuiAppEmpty.tsx b/apps/wallet/src/ui/app/components/sui-apps/SuiAppEmpty.tsx deleted file mode 100644 index 68a2fb010d81c..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/SuiAppEmpty.tsx +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; - -const appEmptyStyle = cva(['flex gap-3 p-3.75 h-28'], { - variants: { - displayType: { - full: 'w-full', - card: 'bg-white flex flex-col p-3.75 box-border w-full rounded-2xl h-32 box-border w-full rounded-2xl border border-solid border-gray-40', - }, - }, - defaultVariants: { - displayType: 'full', - }, -}); - -export interface SuiAppEmptyProps extends VariantProps {} - -export function SuiAppEmpty({ ...styleProps }: SuiAppEmptyProps) { - return ( -
    -
    -
    - {styleProps.displayType === 'full' ? ( - <> -
    -
    -
    - - ) : ( -
    -
    -
    -
    - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/sui-apps/index.tsx b/apps/wallet/src/ui/app/components/sui-apps/index.tsx deleted file mode 100644 index 5fba8b3f0624c..0000000000000 --- a/apps/wallet/src/ui/app/components/sui-apps/index.tsx +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Heading } from '_app/shared/heading'; -import { Text } from '_app/shared/text'; -import { useAppSelector } from '_hooks'; -import { FEATURES } from '_src/shared/experimentation/features'; -import { prepareLinkToCompare } from '_src/shared/utils'; -import { useFeature } from '@growthbook/growthbook-react'; -import { useMemo } from 'react'; -import { useParams } from 'react-router-dom'; - -import { permissionsSelectors } from '../../redux/slices/permissions'; -import { AppsPageBanner } from './Banner'; -import { SuiApp, type DAppEntry } from './SuiApp'; -import { SuiAppEmpty } from './SuiAppEmpty'; - -function AppsPlayGround() { - const ecosystemApps = useFeature(FEATURES.WALLET_DAPPS).value; - const { tagName } = useParams(); - - const filteredEcosystemApps = useMemo(() => { - if (!ecosystemApps) { - return []; - } else if (tagName) { - return ecosystemApps.filter((app) => app.tags.includes(tagName)); - } - return ecosystemApps; - }, [ecosystemApps, tagName]); - - const allPermissions = useAppSelector(permissionsSelectors.selectAll); - const linkToPermissionID = useMemo(() => { - const map = new Map(); - for (const aPermission of allPermissions) { - map.set(prepareLinkToCompare(aPermission.origin), aPermission.id); - if (aPermission.pagelink) { - map.set(prepareLinkToCompare(aPermission.pagelink), aPermission.id); - } - } - return map; - }, [allPermissions]); - - return ( - <> -
    - - Sui Apps - -
    - - - - {filteredEcosystemApps?.length ? ( -
    - - Apps below are actively curated but do not indicate any endorsement or relationship with - Sui Wallet. Please DYOR. - -
    - ) : null} - - {filteredEcosystemApps?.length ? ( -
    - {filteredEcosystemApps.map((app) => ( - - ))} -
    - ) : ( - - )} - - ); -} - -export default AppsPlayGround; -export { default as ConnectedAppsCard } from './ConnectedAppsCard'; diff --git a/apps/wallet/src/ui/app/components/transactions-card/NoActivityCard.tsx b/apps/wallet/src/ui/app/components/transactions-card/NoActivityCard.tsx deleted file mode 100644 index f57479a62e2d6..0000000000000 --- a/apps/wallet/src/ui/app/components/transactions-card/NoActivityCard.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import { TransferObject16 } from '@mysten/icons'; - -export type NoActivityCardType = { - message: string; -}; - -export function NoActivityCard({ message }: NoActivityCardType) { - return ( -
    - - - {message} - -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx b/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx deleted file mode 100644 index 566a119ca3980..0000000000000 --- a/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { formatAddress } from '@mysten/sui/utils'; - -type TxnTypeProps = { - address: string; - moveCallFnName?: string; - isTransfer: boolean; - isSender: boolean; -}; - -export function TxnTypeLabel({ address, moveCallFnName, isTransfer, isSender }: TxnTypeProps) { - const transferLabel = isSender ? 'To' : 'From'; - const label = isTransfer ? transferLabel : 'Action'; - const content = isTransfer ? formatAddress(address) : moveCallFnName?.replace(/_/g, ' '); - - return content ? ( -
    - - {label}: - -
    - - {content} - -
    -
    - ) : null; -} diff --git a/apps/wallet/src/ui/app/components/transactions-card/TxnIcon.tsx b/apps/wallet/src/ui/app/components/transactions-card/TxnIcon.tsx deleted file mode 100644 index 9206495500987..0000000000000 --- a/apps/wallet/src/ui/app/components/transactions-card/TxnIcon.tsx +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - Account24, - ArrowRight16, - Info16, - Sui, - Swap16, - Unstaked, - WalletActionStake24, -} from '@mysten/icons'; -import cl from 'clsx'; - -import LoadingIndicator from '../loading/LoadingIndicator'; - -const icons = { - Send: ( - - ), - Receive: ( - - ), - Transaction: ( - - ), - Staked: , - Unstaked: , - Rewards: , - Swapped: , - Failed: , - Loading: , - PersonalMessage: , -}; - -interface TxnItemIconProps { - txnFailed?: boolean; - variant: keyof typeof icons; -} - -export function TxnIcon({ txnFailed, variant }: TxnItemIconProps) { - return ( -
    - {icons[txnFailed ? 'Failed' : variant]} -
    - ); -} diff --git a/apps/wallet/src/ui/app/components/transactions-card/TxnImage.tsx b/apps/wallet/src/ui/app/components/transactions-card/TxnImage.tsx deleted file mode 100644 index c2ff0695df388..0000000000000 --- a/apps/wallet/src/ui/app/components/transactions-card/TxnImage.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { NftImage } from '_components/nft-display/NftImage'; -import { useGetNFTMeta } from '_hooks'; -import { cx } from 'class-variance-authority'; - -//TODO merge all NFT image displays -export function TxnImage({ id, actionLabel }: { id: string; actionLabel?: string }) { - const { data: nftMeta } = useGetNFTMeta(id); - - return nftMeta?.imageUrl ? ( -
    - {actionLabel ? ( - - {actionLabel} - - ) : null} -
    - -
    - {nftMeta.name && ( - - {nftMeta.name} - - )} - {nftMeta.description && ( - - {nftMeta.description} - - )} -
    -
    -
    - ) : null; -} diff --git a/apps/wallet/src/ui/app/components/transactions-card/index.tsx b/apps/wallet/src/ui/app/components/transactions-card/index.tsx deleted file mode 100644 index fcf767842d5a7..0000000000000 --- a/apps/wallet/src/ui/app/components/transactions-card/index.tsx +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { DateCard } from '_app/shared/date-card'; -import { Text } from '_app/shared/text'; -import { useGetTxnRecipientAddress } from '_hooks'; -import { useRecognizedPackages } from '_src/ui/app/hooks/useRecognizedPackages'; -import { getLabel, useTransactionSummary } from '@mysten/core'; -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { Link } from 'react-router-dom'; - -import { TxnTypeLabel } from './TxnActionLabel'; -import { TxnIcon } from './TxnIcon'; - -export function TransactionCard({ - txn, - address, -}: { - txn: SuiTransactionBlockResponse; - address: string; -}) { - const executionStatus = txn.effects?.status.status; - const recognizedPackagesList = useRecognizedPackages(); - - const summary = useTransactionSummary({ - transaction: txn, - currentAddress: address, - recognizedPackagesList, - }); - - // we only show Sui Transfer amount or the first non-Sui transfer amount - - const recipientAddress = useGetTxnRecipientAddress({ txn, address }); - - const isSender = address === txn.transaction?.data.sender; - - const error = txn.effects?.status.error; - - // Transition label - depending on the transaction type and amount - // Epoch change without amount is delegation object - // Special case for staking and unstaking move call transaction, - // For other transaction show Sent or Received - - // TODO: Support programmable tx: - // Show sui symbol only if transfer transferAmount coinType is SUI_TYPE_ARG, staking or unstaking - const showSuiSymbol = false; - - const timestamp = txn.timestampMs; - - return ( - -
    -
    - -
    -
    - {error ? ( -
    -
    - - Transaction Failed - - -
    - - {error} - -
    -
    - {/* {transferAmountComponent} */} -
    - ) : ( - <> -
    -
    - - {summary?.label} - - {showSuiSymbol && ( - - SUI - - )} -
    - {/* {transferAmountComponent} */} -
    - - {/* TODO: Support programmable tx: */} - - {/* {objectId && } */} - - )} - - {timestamp && } -
    -
    - - ); -} diff --git a/apps/wallet/src/ui/app/components/user-approve-container/index.tsx b/apps/wallet/src/ui/app/components/user-approve-container/index.tsx deleted file mode 100644 index f01fa49403ae8..0000000000000 --- a/apps/wallet/src/ui/app/components/user-approve-container/index.tsx +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { type PermissionType } from '_src/shared/messaging/messages/payloads/permissions'; -import { Transaction } from '@mysten/sui/transactions'; -import cn from 'clsx'; -import { useMemo, useState } from 'react'; -import type { ReactNode } from 'react'; -import { useParams } from 'react-router-dom'; - -import { useAppSelector } from '../../hooks'; -import { useAccountByAddress } from '../../hooks/useAccountByAddress'; -import { type RootState } from '../../redux/RootReducer'; -import { txRequestsSelectors } from '../../redux/slices/transaction-requests'; -import { Button } from '../../shared/ButtonUI'; -import { UnlockAccountButton } from '../accounts/UnlockAccountButton'; -import { DAppInfoCard } from '../DAppInfoCard'; -import { ScamOverlay } from '../known-scam-overlay'; -import { RequestType } from '../known-scam-overlay/types'; -import { useShowScamWarning } from '../known-scam-overlay/useShowScamWarning'; - -type UserApproveContainerProps = { - children: ReactNode | ReactNode[]; - origin: string; - originFavIcon?: string; - rejectTitle: string; - approveTitle: string; - approveDisabled?: boolean; - approveLoading?: boolean; - onSubmit: (approved: boolean) => Promise; - isWarning?: boolean; - addressHidden?: boolean; - address?: string | null; - scrollable?: boolean; - blended?: boolean; - permissions?: PermissionType[]; - checkAccountLock?: boolean; -}; - -export function UserApproveContainer({ - origin, - originFavIcon, - children, - rejectTitle, - approveTitle, - approveDisabled = false, - approveLoading = false, - onSubmit, - isWarning, - addressHidden = false, - address, - permissions, - checkAccountLock, -}: UserApproveContainerProps) { - const [submitting, setSubmitting] = useState(false); - const [scamOverlayDismissed, setScamOverlayDismissed] = useState(false); - - const handleDismissScamOverlay = () => { - ampli.bypassedScamWarning({ hostname: new URL(origin).hostname }); - setScamOverlayDismissed(true); - }; - - const handleOnResponse = async (allowed: boolean) => { - setSubmitting(true); - await onSubmit(allowed); - setSubmitting(false); - }; - - const { data: selectedAccount } = useAccountByAddress(address); - const parsedOrigin = useMemo(() => new URL(origin), [origin]); - const { requestID } = useParams(); - const requestSelector = useMemo( - () => (state: RootState) => - requestID ? txRequestsSelectors.selectById(state, requestID) : null, - [requestID], - ); - const request = useAppSelector(requestSelector); - - const transaction = useMemo(() => { - if (request && request.tx && 'data' in request.tx) { - const transaction = Transaction.from(request.tx.data); - transaction.setSender(request.tx.account); - return transaction; - } - }, [request]); - const message = request && request.tx && 'message' in request.tx ? request.tx.message : undefined; - - const { - data: preflight, - isPending: isDomainCheckLoading, - isError, - } = useShowScamWarning({ - url: parsedOrigin, - requestType: message - ? RequestType.SIGN_MESSAGE - : transaction - ? RequestType.SIGN_TRANSACTION - : RequestType.CONNECT, - transaction, - requestId: requestID!, - }); - - return ( - <> - {!scamOverlayDismissed && !!preflight && ( - handleOnResponse(false)} - onClickContinue={handleDismissScamOverlay} - /> - )} -
    -
    - -
    {children}
    -
    -
    -
    - {!checkAccountLock || !selectedAccount?.isLocked ? ( - <> -
    -
    -
    - - ); -} diff --git a/apps/wallet/src/ui/app/experimentation/feature-gating.ts b/apps/wallet/src/ui/app/experimentation/feature-gating.ts deleted file mode 100644 index 5fce93e247b3f..0000000000000 --- a/apps/wallet/src/ui/app/experimentation/feature-gating.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { GrowthBook } from '@growthbook/growthbook'; - -// This is a separate growthbook instance for the wallet UI, with flag values synced from the service worker. -export const growthbook = new GrowthBook(); diff --git a/apps/wallet/src/ui/app/helpers/accounts.ts b/apps/wallet/src/ui/app/helpers/accounts.ts deleted file mode 100644 index 357ccdd298b7f..0000000000000 --- a/apps/wallet/src/ui/app/helpers/accounts.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { type AccountType, type SerializedUIAccount } from '_src/background/accounts/Account'; -import { isMnemonicSerializedUiAccount } from '_src/background/accounts/MnemonicAccount'; -import { isZkLoginAccountSerializedUI } from '_src/background/accounts/zklogin/ZkLoginAccount'; - -function getKey(account: SerializedUIAccount): string { - if (isMnemonicSerializedUiAccount(account)) return account.sourceID; - if (isZkLoginAccountSerializedUI(account)) return account.provider; - return account.type; -} - -export const defaultSortOrder: AccountType[] = [ - 'zkLogin', - 'mnemonic-derived', - 'imported', - 'ledger', - 'qredo', -]; - -export function getAccountBackgroundByType(account: SerializedUIAccount) { - if (!isZkLoginAccountSerializedUI(account)) return 'bg-gradients-graph-cards'; - switch (account.provider) { - case 'google': - return 'bg-google bg-no-repeat bg-cover'; - case 'twitch': - return 'bg-twitch-image bg-no-repeat bg-cover'; - default: - return `bg-gradients-graph-cards`; - } -} - -export function groupByType(accounts: SerializedUIAccount[]) { - return accounts.reduce( - (acc, account) => { - const byType = acc[account.type] || (acc[account.type] = {}); - const key = getKey(account); - (byType[key] || (byType[key] = [])).push(account); - return acc; - }, - defaultSortOrder.reduce( - (acc, type) => { - acc[type] = {}; - return acc; - }, - {} as Record>, - ), - ); -} diff --git a/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts b/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts deleted file mode 100644 index 940ed4faed293..0000000000000 --- a/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; - -// TODO: Support programmable transactions: -export function checkStakingTxn(_txn: SuiTransactionBlockResponse) { - return false; -} diff --git a/apps/wallet/src/ui/app/helpers/errorMessages.ts b/apps/wallet/src/ui/app/helpers/errorMessages.ts deleted file mode 100644 index 0ea4306af6138..0000000000000 --- a/apps/wallet/src/ui/app/helpers/errorMessages.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { LockedDeviceError, StatusCodes } from '@ledgerhq/errors'; - -import { - isLedgerTransportStatusError, - LedgerConnectionFailedError, - LedgerDeviceNotFoundError, - LedgerNoTransportMechanismError, -} from '../components/ledger/ledgerErrors'; - -/** - * Helper method for producing user-friendly error messages from Signer operations - * from SignerWithProvider instances (e.g., signTransaction, getAddress, and so forth) - */ -export function getSignerOperationErrorMessage(error: unknown) { - return ( - getLedgerConnectionErrorMessage(error) || - getSuiApplicationErrorMessage(error) || - (error as Error).message || - 'Something went wrong.' - ); -} - -/** - * Helper method for producing user-friendly error messages from Ledger connection errors - */ -export function getLedgerConnectionErrorMessage(error: unknown) { - if (error instanceof LedgerConnectionFailedError) { - return 'Ledger connection failed. Try again.'; - } else if (error instanceof LedgerNoTransportMechanismError) { - return "Your browser unfortunately doesn't support USB or HID."; - } else if (error instanceof LedgerDeviceNotFoundError) { - return 'Connect your Ledger device and try again.'; - } else if (error instanceof LockedDeviceError) { - return 'Your device is locked. Unlock it and try again.'; - } - return null; -} - -/** - * Helper method for producing user-friendly error messages from errors that arise from - * operations on the Sui Ledger application - */ -export function getSuiApplicationErrorMessage(error: unknown) { - if (error instanceof LockedDeviceError) { - return 'Your device is locked. Unlock it and try again.'; - } else if (isLedgerTransportStatusError(error)) { - if (error.statusCode === StatusCodes.INS_NOT_SUPPORTED) { - return "Something went wrong. We're working on it!"; - } else { - return 'Make sure the Sui app is open on your device.'; - } - } - return null; -} diff --git a/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts b/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts deleted file mode 100644 index 6872ad3e8fcfa..0000000000000 --- a/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { USDC_TYPE_ARG } from '_pages/swap/utils'; -import { type CoinBalance } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -// Sort tokens by symbol and total balance -// Move this to the API backend -// Filter out tokens with zero balance -export function filterAndSortTokenBalances(tokens: CoinBalance[]) { - return tokens - .filter((token) => Number(token.totalBalance) > 0) - .sort((a, b) => { - if (a.coinType === SUI_TYPE_ARG) { - return -1; - } - if (b.coinType === SUI_TYPE_ARG) { - return 1; - } - if (a.coinType === USDC_TYPE_ARG) { - return -1; - } - if (b.coinType === USDC_TYPE_ARG) { - return 1; - } - return (getCoinSymbol(a.coinType) + Number(a.totalBalance)).localeCompare( - getCoinSymbol(b.coinType) + Number(b.totalBalance), - ); - }); -} - -export function getCoinSymbol(coinTypeArg: string) { - return coinTypeArg.substring(coinTypeArg.lastIndexOf(':') + 1); -} diff --git a/apps/wallet/src/ui/app/helpers/formatDate.ts b/apps/wallet/src/ui/app/helpers/formatDate.ts deleted file mode 100644 index f9325bf156bff..0000000000000 --- a/apps/wallet/src/ui/app/helpers/formatDate.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -// TODO - handle multiple date formats -// Wed Aug 05 -// -type Show = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'weekday'; -export default function formatDate(timeStamp: number, show: Show[]): string { - const date = new Date(timeStamp); - if (!(date instanceof Date) || !show.length) return ''; - - const options = { - year: 'numeric', - month: 'short', - day: 'numeric', - hour: 'numeric', - weekday: 'short', - minute: 'numeric', - second: 'numeric', - }; - - const formatOptions = show.reduce((accumulator, current: Show) => { - const responseObj = { - ...accumulator, - ...{ [current]: options[current] }, - }; - return responseObj; - }, {}); - - return new Intl.DateTimeFormat('en-US', formatOptions).format(date); -} diff --git a/apps/wallet/src/ui/app/helpers/getAmount.ts b/apps/wallet/src/ui/app/helpers/getAmount.ts deleted file mode 100644 index d88c1026f1e35..0000000000000 --- a/apps/wallet/src/ui/app/helpers/getAmount.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiEvent, SuiTransactionBlockKind, TransactionEffects } from '@mysten/sui/client'; - -type FormattedBalance = { - amount?: number | null; - coinType?: string | null; - recipientAddress: string; -}[]; - -export function getAmount( - _txnData: SuiTransactionBlockKind, - _txnEffect: TransactionEffects, - _events: SuiEvent[], -): FormattedBalance | null { - // TODO: Support programmable transactions: - return null; -} diff --git a/apps/wallet/src/ui/app/helpers/getEventsSummary.ts b/apps/wallet/src/ui/app/helpers/getEventsSummary.ts deleted file mode 100644 index db984b2469dee..0000000000000 --- a/apps/wallet/src/ui/app/helpers/getEventsSummary.ts +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export {}; - -// import { -// getCoinBalanceChangeEvent, -// getTransferObjectEvent, -// isEventType, -// type TransactionEvents, -// } from '@mysten/sui'; - -// export type CoinsMetaProps = { -// amount: number; -// coinType: string; -// receiverAddress: string; -// }; - -// export type TxnMetaResponse = { -// objectIDs: string[]; -// coins: CoinsMetaProps[]; -// }; - -// export function getEventsSummary( -// events: TransactionEvents, -// address: string -// ): TxnMetaResponse { -// const coinsMeta = {} as { [coinType: string]: CoinsMetaProps }; -// const objectIDs: string[] = []; - -// events.forEach((event) => { -// // Aggregate coinBalanceChange by coinType and address -// // A net positive amount means the user received coins -// // A net negative amount means the user sent coins -// if ( -// event.type === 'coinBalanceChange' && -// event?.content?.changeType && -// ['Receive', 'Pay'].includes(event?.content?.changeType) -// ) { -// const coinBalanceChange = getCoinBalanceChangeEvent(event)!; -// const { coinType, amount, owner, sender } = coinBalanceChange; - -// const AddressOwner = -// owner !== 'Immutable' && 'AddressOwner' in owner -// ? owner.AddressOwner -// : null; - -// // ChangeEpoch txn includes coinBalanceChange event for other addresses -// if ( -// AddressOwner === address || -// (address === sender && AddressOwner) -// ) { -// coinsMeta[`${AddressOwner}${coinType}`] = { -// amount: -// (coinsMeta[`${AddressOwner}${coinType}`]?.amount || 0) + -// +amount, -// coinType: coinType, -// receiverAddress: AddressOwner, -// }; -// } -// } - -// // return objectIDs of the transfer objects -// if (isEventType(event, 'transferObject')) { -// const transferObject = getTransferObjectEvent(event)!; -// const { AddressOwner } = transferObject.recipient as { -// AddressOwner: string; -// }; -// if (AddressOwner === address) { -// objectIDs.push(transferObject?.objectId); -// } -// } -// }); - -// return { -// objectIDs, -// coins: Object.values(coinsMeta), -// }; -// } diff --git a/apps/wallet/src/ui/app/helpers/index.ts b/apps/wallet/src/ui/app/helpers/index.ts deleted file mode 100644 index e95874feb45a2..0000000000000 --- a/apps/wallet/src/ui/app/helpers/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export { default as formatDate } from './formatDate'; -export { default as notEmpty } from './notEmptyCheck'; -export { parseAmount } from './parseAmount'; -// export { getEventsSummary } from './getEventsSummary'; -export { getAmount } from './getAmount'; -export { checkStakingTxn } from './checkStakingTxn'; -export { filterAndSortTokenBalances } from './filterAndSortTokenBalances'; diff --git a/apps/wallet/src/ui/app/helpers/notEmptyCheck.ts b/apps/wallet/src/ui/app/helpers/notEmptyCheck.ts deleted file mode 100644 index 86a4140b704d4..0000000000000 --- a/apps/wallet/src/ui/app/helpers/notEmptyCheck.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export default function notEmpty(value: TValue | null | undefined): value is TValue { - if (value === null || value === undefined) return false; - return true; -} diff --git a/apps/wallet/src/ui/app/helpers/parseAmount.ts b/apps/wallet/src/ui/app/helpers/parseAmount.ts deleted file mode 100644 index cd87a9d18593e..0000000000000 --- a/apps/wallet/src/ui/app/helpers/parseAmount.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import BigNumber from 'bignumber.js'; - -export function parseAmount(amount: string, coinDecimals: number) { - try { - return BigInt(new BigNumber(amount).shiftedBy(coinDecimals).integerValue().toString()); - } catch (e) { - return BigInt(0); - } -} diff --git a/apps/wallet/src/ui/app/helpers/query-client-keys.ts b/apps/wallet/src/ui/app/helpers/query-client-keys.ts deleted file mode 100644 index 1fcf5cfd91b96..0000000000000 --- a/apps/wallet/src/ui/app/helpers/query-client-keys.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export const accountsQueryKey = ['background', 'client', 'accounts'] as const; diff --git a/apps/wallet/src/ui/app/helpers/queryClient.ts b/apps/wallet/src/ui/app/helpers/queryClient.ts deleted file mode 100644 index 151844399c0c3..0000000000000 --- a/apps/wallet/src/ui/app/helpers/queryClient.ts +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { QueryClient } from '@tanstack/react-query'; -import { type PersistedClient, type Persister } from '@tanstack/react-query-persist-client'; -import { del, get, set } from 'idb-keyval'; - -export const queryClient = new QueryClient({ - defaultOptions: { - queries: { - // Only retry once by default: - retry: 1, - // Default stale time to 30 seconds, which seems like a sensible tradeoff between network requests and stale data. - staleTime: 30 * 1000, - // Default cache time to 24 hours, so that data will remain in the cache and improve wallet loading UX. - gcTime: 24 * 60 * 60 * 1000, - // Disable automatic interval fetching - refetchInterval: 0, - refetchIntervalInBackground: false, - refetchOnWindowFocus: false, - - refetchOnMount: true, - }, - }, -}); - -function createIDBPersister(idbValidKey: IDBValidKey) { - return { - persistClient: async (client: PersistedClient) => { - await set(idbValidKey, client); - }, - restoreClient: async () => { - return await get(idbValidKey); - }, - removeClient: async () => { - await del(idbValidKey); - }, - } as Persister; -} - -export const persister = createIDBPersister('queryClient.v1'); diff --git a/apps/wallet/src/ui/app/helpers/sentry.ts b/apps/wallet/src/ui/app/helpers/sentry.ts deleted file mode 100644 index fd2c1d26395a9..0000000000000 --- a/apps/wallet/src/ui/app/helpers/sentry.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { growthbook } from '_src/ui/app/experimentation/feature-gating'; -import * as Sentry from '@sentry/react'; - -import { getSentryConfig } from '../../../shared/sentry-config'; - -export default function initSentry() { - Sentry.init( - getSentryConfig({ - integrations: [new Sentry.BrowserTracing()], - tracesSampler: () => { - return growthbook.getFeatureValue('wallet-sentry-tracing', 0); - }, - }), - ); -} diff --git a/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts b/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts deleted file mode 100644 index 0e35c5610c012..0000000000000 --- a/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { decodeSuiPrivateKey } from '@mysten/sui/cryptography'; -import { z } from 'zod'; - -export const privateKeyValidation = z - .string() - .trim() - .nonempty('Private Key is required.') - .transform((privateKey, context) => { - try { - decodeSuiPrivateKey(privateKey); - } catch (error) { - context.addIssue({ - code: 'custom', - message: - 'Invalid Private Key, please use a Bech32 encoded 33-byte string. Learn more: https://github.com/sui-foundation/sips/blob/main/sips/sip-15.md', - }); - return z.NEVER; - } - return privateKey; - }); diff --git a/apps/wallet/src/ui/app/hooks/deepbook/index.ts b/apps/wallet/src/ui/app/hooks/deepbook/index.ts deleted file mode 100644 index 13e47746e5943..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export * from './useDeepBookConfigs'; -export * from './useRecognizedCoins'; -export * from './useDeepbookPools'; -export * from './useGetEstimate'; diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useDeepBookConfigs.ts b/apps/wallet/src/ui/app/hooks/deepbook/useDeepBookConfigs.ts deleted file mode 100644 index 0abf579c76130..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/useDeepBookConfigs.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { Coins } from '_pages/swap/constants'; -import { FEATURES } from '_shared/experimentation/features'; -import { useFeatureValue } from '@growthbook/growthbook-react'; - -export const mainnetDeepBook: { - pools: Record; - coinsMap: Record; -} = { - pools: { - SUI_USDC: [ - '0x4405b50d791fd3346754e8171aaab6bc2ed26c2c46efdd033c14b30ae507ac33', - '0x7f526b1263c4b91b43c9e646419b5696f424de28dda3c1e6658cc0a54558baa7', - ], - WETH_USDC: ['0xd9e45ab5440d61cc52e3b2bd915cdd643146f7593d587c715bc7bfa48311d826'], - TBTC_USDC: ['0xf0f663cf87f1eb124da2fc9be813e0ce262146f3df60bc2052d738eb41a25899'], - USDT_USDC: ['0x5deafda22b6b86127ea4299503362638bea0ca33bb212ea3a67b029356b8b955'], - }, - coinsMap: { - [Coins.SUI]: '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI', - [Coins.USDC]: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN', - [Coins.USDT]: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', - [Coins.WETH]: '0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN', - [Coins.TBTC]: '0xbc3a676894871284b3ccfb2eec66f428612000e2a6e6d23f592ce8833c27c973::coin::COIN', - }, -}; - -export function useDeepBookConfigs() { - return useFeatureValue(FEATURES.DEEP_BOOK_CONFIGS, mainnetDeepBook); -} diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useDeepbookPools.ts b/apps/wallet/src/ui/app/hooks/deepbook/useDeepbookPools.ts deleted file mode 100644 index ed6a2cf1e4e74..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/useDeepbookPools.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { DEEPBOOK_KEY } from '_pages/swap/constants'; -import { useDeepBookContext } from '_shared/deepBook/context'; -import { useQuery } from '@tanstack/react-query'; - -export function useDeepbookPools() { - const deepBookClient = useDeepBookContext().client; - - return useQuery({ - queryKey: [DEEPBOOK_KEY, 'get-all-pools'], - queryFn: () => deepBookClient.getAllPools({}), - }); -} diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts b/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts deleted file mode 100644 index 2810a6396cfb2..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useLotSize } from '_app/hooks/deepbook/useLotSize'; -import { useActiveAccount } from '_app/hooks/useActiveAccount'; -import { type WalletSigner } from '_app/WalletSigner'; -import { DEEPBOOK_KEY, WALLET_FEES_PERCENTAGE } from '_pages/swap/constants'; -import { useDeepBookContext } from '_shared/deepBook/context'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { type DeepBookClient } from '@mysten/deepbook'; -import { type CoinStruct, type SuiClient } from '@mysten/sui/client'; -import { Transaction } from '@mysten/sui/transactions'; -import * as Sentry from '@sentry/react'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; - -const MAX_COINS_PER_REQUEST = 10; -const ESTIMATE_RETRY_COUNT = 3; -const NUMBER_EXPECTED_BALANCE_CHANGES = 3; - -async function getCoinsByBalance({ - coinType, - balance, - suiClient, - address, -}: { - coinType: string; - balance: string; - suiClient: SuiClient; - address: string; -}) { - let cursor: string | undefined | null = null; - let currentBalance = 0n; - let hasNextPage = true; - const coins = []; - - const bigIntBalance = BigInt(new BigNumber(balance).integerValue(BigNumber.ROUND_UP).toString()); - - while (currentBalance < bigIntBalance && hasNextPage) { - const { data, nextCursor } = await suiClient.getCoins({ - owner: address, - coinType, - cursor, - limit: MAX_COINS_PER_REQUEST, - }); - - if (!data || !data.length) { - break; - } - - for (const coin of data) { - currentBalance += BigInt(coin.balance); - coins.push(coin); - - if (currentBalance >= bigIntBalance) { - break; - } - } - - cursor = nextCursor; - hasNextPage = !!nextCursor; - } - - if (!coins.length) { - throw new Error('No coins found in balance'); - } - - return coins; -} - -function formatBalance(balance: string, lotSize: number) { - const balanceBigNumber = new BigNumber(balance); - const remainder = balanceBigNumber.mod(lotSize); - - if (remainder.isEqualTo(0)) { - return balanceBigNumber.toString(); - } - - const roundedDownBalance = balanceBigNumber.minus(remainder); - return roundedDownBalance.abs().toString(); -} - -function getWalletFee(balance: string) { - return new BigNumber(balance) - .times(WALLET_FEES_PERCENTAGE / 100) - .integerValue(BigNumber.ROUND_DOWN) - .toString(); -} - -function getBalanceAndWalletFees(balance: string, totalBalance: string, conversionRate: number) { - const bigNumberTotalBalance = new BigNumber(totalBalance).shiftedBy(conversionRate); - const bigNumberBalance = new BigNumber(balance); - const walletFees = getWalletFee(bigNumberBalance.toString()); - const balanceAndWalletFees = bigNumberBalance.plus(walletFees); - - if (balanceAndWalletFees.isGreaterThan(bigNumberTotalBalance)) { - /** - * If the balance + wallet fees is greater than the total balance, we need to - * recalculate the balance and wallet fees. - */ - const remainingBalance = bigNumberBalance.minus(new BigNumber(walletFees).times(2)).toString(); - const newWalletFee = getWalletFee(remainingBalance); - - return { - actualBalance: remainingBalance, - actualWalletFee: newWalletFee, - }; - } - - return { - actualBalance: bigNumberBalance.toString(), - actualWalletFee: walletFees, - }; -} - -async function getPlaceMarketOrderTxn({ - deepBookClient, - poolId, - accountCapId, - address, - isAsk, - baseBalance, - quoteBalance, - quoteCoins, - walletFeeAddress, - totalBaseBalance, - totalQuoteBalance, - baseConversionRate, - quoteConversionRate, - lotSize, -}: { - deepBookClient: DeepBookClient; - poolId: string; - accountCapId: string; - address: string; - isAsk: boolean; - baseBalance: string; - quoteBalance: string; - baseCoins: CoinStruct[]; - quoteCoins: CoinStruct[]; - walletFeeAddress: string; - totalBaseBalance: string; - totalQuoteBalance: string; - baseConversionRate: number; - quoteConversionRate: number; - lotSize: string; -}) { - const txb = new Transaction(); - const accountCap = accountCapId || deepBookClient.createAccountCap(txb); - - let walletFeeCoin; - let txnResult; - - if (isAsk) { - const { actualBalance, actualWalletFee } = getBalanceAndWalletFees( - baseBalance, - totalBaseBalance, - baseConversionRate, - ); - - const actualBalanceFormatted = formatBalance(actualBalance, parseInt(lotSize)); - - const swapCoin = txb.splitCoins(txb.gas, [actualBalanceFormatted]); - walletFeeCoin = txb.splitCoins(txb.gas, [actualWalletFee]); - txnResult = await deepBookClient.placeMarketOrder( - accountCap, - poolId, - BigInt(actualBalanceFormatted), - 'ask', - swapCoin, - undefined, - undefined, - address, - txb, - ); - } else { - const primaryCoinInput = txb.object(quoteCoins[0].coinObjectId); - const restCoins = quoteCoins.slice(1); - - if (restCoins.length) { - txb.mergeCoins( - primaryCoinInput, - restCoins.map((coin) => txb.object(coin.coinObjectId)), - ); - } - - const { actualBalance, actualWalletFee } = getBalanceAndWalletFees( - quoteBalance, - totalQuoteBalance, - quoteConversionRate, - ); - - const [swapCoin, walletCoin] = txb.splitCoins(primaryCoinInput, [ - actualBalance, - actualWalletFee, - ]); - - txnResult = await deepBookClient.swapExactQuoteForBase( - poolId, - swapCoin, - BigInt(actualBalance), - address, - undefined, - txb, - ); - - walletFeeCoin = walletCoin; - } - - if (!accountCapId) { - txnResult.transferObjects([accountCap], address); - } - - if (walletFeeCoin) txnResult.transferObjects([walletFeeCoin], walletFeeAddress); - - return txnResult; -} - -export function useGetEstimate({ - accountCapId, - signer, - coinType, - poolId, - baseBalance, - quoteBalance, - isAsk, - totalBaseBalance, - totalQuoteBalance, - baseConversionRate, - quoteConversionRate, - enabled, - amount, -}: { - accountCapId: string; - signer: WalletSigner | null; - coinType: string; - poolId: string; - baseBalance: string; - quoteBalance: string; - isAsk: boolean; - totalBaseBalance: string; - totalQuoteBalance: string; - baseConversionRate: number; - quoteConversionRate: number; - enabled?: boolean; - amount: string; -}) { - const walletFeeAddress = useDeepBookContext().walletFeeAddress; - const queryClient = useQueryClient(); - const suiClient = useSuiClient(); - const activeAccount = useActiveAccount(); - const activeAddress = activeAccount?.address; - const deepBookClient = useDeepBookContext().client; - const lotSize = useLotSize(poolId); - - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: [ - DEEPBOOK_KEY, - 'get-estimate', - poolId, - accountCapId, - coinType, - activeAddress, - baseBalance, - quoteBalance, - isAsk, - totalBaseBalance, - totalQuoteBalance, - baseConversionRate, - quoteConversionRate, - lotSize, - amount, - ], - queryFn: async () => { - const sentryTransaction = Sentry.startTransaction({ - name: 'defi-swap', - op: 'get-estimate', - data: { - coinType, - isAsk, - swapAmount: amount, - maxAvailableBalanceToSwap: isAsk ? totalBaseBalance : totalQuoteBalance, - }, - }); - - try { - const [baseCoins, quoteCoins] = await Promise.all([ - getCoinsByBalance({ - coinType, - balance: baseBalance, - suiClient, - address: activeAddress!, - }), - getCoinsByBalance({ - coinType, - balance: quoteBalance, - suiClient, - address: activeAddress!, - }), - ]); - - if (isAsk ? !baseCoins.length : !quoteCoins.length) { - throw new Error('No coins found in balance'); - } - - const txn = await getPlaceMarketOrderTxn({ - deepBookClient, - poolId, - accountCapId, - address: activeAddress!, - isAsk, - baseCoins, - quoteCoins, - baseBalance, - quoteBalance, - walletFeeAddress, - totalBaseBalance, - totalQuoteBalance, - baseConversionRate, - quoteConversionRate, - lotSize, - }); - - if (!accountCapId) { - await queryClient.invalidateQueries({ queryKey: ['get-owned-objects'] }); - } - - const dryRunResponse = await signer!.dryRunTransactionBlock({ transactionBlock: txn }); - - if (dryRunResponse.balanceChanges.length < NUMBER_EXPECTED_BALANCE_CHANGES) { - throw new Error('Not enough balance. Please lower swap amount'); - } - - return { - txn, - dryRunResponse, - }; - } catch (error) { - sentryTransaction.setStatus('failed_precondition'); - Sentry.captureException(error); - throw error; - } finally { - sentryTransaction.finish(); - } - }, - enabled: - enabled && - !!baseBalance && - baseBalance !== '0' && - !!quoteBalance && - quoteBalance !== '0' && - !!signer && - !!activeAddress && - !!amount, - retry: ESTIMATE_RETRY_COUNT, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useLotSize.ts b/apps/wallet/src/ui/app/hooks/deepbook/useLotSize.ts deleted file mode 100644 index 7b25ed13b1a25..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/useLotSize.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useGetObject } from '@mysten/core'; - -export function useLotSize(poolId: string) { - const { data } = useGetObject(poolId); - const objectFields = - data?.data?.content?.dataType === 'moveObject' ? data?.data?.content?.fields : null; - - return (objectFields as Record)?.lot_size; -} diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts b/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts deleted file mode 100644 index 7280d199ce6dc..0000000000000 --- a/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useDeepBookConfigs } from '_app/hooks/deepbook/useDeepBookConfigs'; -import { useDeepBookContext } from '_shared/deepBook/context'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -export function useRecognizedCoins() { - const coinsMap = useDeepBookContext().configs.coinsMap; - return Object.values(coinsMap); -} - -export function useAllowedSwapCoinsList() { - const deepBookConfigs = useDeepBookConfigs(); - const coinsMap = deepBookConfigs.coinsMap; - - return [SUI_TYPE_ARG, coinsMap.SUI, coinsMap.USDC]; -} diff --git a/apps/wallet/src/ui/app/hooks/index.ts b/apps/wallet/src/ui/app/hooks/index.ts deleted file mode 100644 index b6dc4e0e4bf9f..0000000000000 --- a/apps/wallet/src/ui/app/hooks/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export { default as useAppDispatch } from './useAppDispatch'; -export { default as useAppSelector } from './useAppSelector'; -export { default as useInitializedGuard } from './useInitializedGuard'; -export { default as useFullscreenGuard } from './useFullscreenGuard'; -export { default as useMediaUrl, parseIpfsUrl } from './useMediaUrl'; -export { default as useOnClickOutside } from './useOnClickOutside'; -export { default as useOnKeyboardEvent } from './useOnKeyboardEvent'; -export { default as useFileExtensionType } from './useFileExtensionType'; -export { default as useNFTBasicData } from './useNFTBasicData'; -export { useGetNFTMeta } from './useGetNFTMeta'; -export { useTransactionDryRun } from './useTransactionDryRun'; -export { useGetTxnRecipientAddress } from './useGetTxnRecipientAddress'; -export { useQueryTransactionsByAddress } from './useQueryTransactionsByAddress'; -export { useGetTransferAmount } from './useGetTransferAmount'; -export { useOwnedNFT } from './useOwnedNFT'; -export { useSortedCoinsByCategories } from './useSortedCoinsByCategories'; -export * from './useTransactionData'; -export * from './useActiveAddress'; -export * from './useGetAllCoins'; -export * from './useCoinsReFetchingConfig'; -export * from './deepbook'; diff --git a/apps/wallet/src/ui/app/hooks/useAccountByAddress.ts b/apps/wallet/src/ui/app/hooks/useAccountByAddress.ts deleted file mode 100644 index 6fc69aea216b1..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAccountByAddress.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMemo } from 'react'; - -import { useAccounts } from './useAccounts'; - -export function useAccountByAddress(accountAddress?: string | null) { - const allAccountsData = useAccounts(); - const account = useMemo( - () => - (accountAddress && allAccountsData.data?.find(({ address }) => address === accountAddress)) || - null, - [allAccountsData.data, accountAddress], - ); - return { ...allAccountsData, data: account }; -} diff --git a/apps/wallet/src/ui/app/hooks/useAccountGroups.ts b/apps/wallet/src/ui/app/hooks/useAccountGroups.ts deleted file mode 100644 index d482dfe23f8a9..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAccountGroups.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMemo } from 'react'; - -import { defaultSortOrder, groupByType } from '../helpers/accounts'; -import { useAccounts } from './useAccounts'; - -export function useAccountGroups() { - const { data: accounts } = useAccounts(); - - const sortedAndGroupedAccounts = useMemo(() => { - return groupByType(accounts ?? []); - }, [accounts]); - - const list = () => { - return defaultSortOrder.flatMap((type) => { - const group = sortedAndGroupedAccounts[type]; - return Object.values(group).flat(); - }); - }; - - return { ...sortedAndGroupedAccounts, list }; -} diff --git a/apps/wallet/src/ui/app/hooks/useAccountSources.ts b/apps/wallet/src/ui/app/hooks/useAccountSources.ts deleted file mode 100644 index 008cb3d809484..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAccountSources.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type AccountSourceSerializedUI } from '_src/background/account-sources/AccountSource'; -import { useQuery } from '@tanstack/react-query'; - -import { useBackgroundClient } from './useBackgroundClient'; - -export const accountSourcesQueryKey = ['background', 'client', 'account', 'sources'] as const; - -export function useAccountSources() { - const backgroundClient = useBackgroundClient(); - return useQuery({ - queryKey: accountSourcesQueryKey, - queryFn: () => backgroundClient.getStoredEntities('accountSources'), - gcTime: 30 * 1000, - staleTime: 15 * 1000, - refetchInterval: 30 * 1000, - meta: { skipPersistedCache: true }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useAccounts.ts b/apps/wallet/src/ui/app/hooks/useAccounts.ts deleted file mode 100644 index 1d5acad5f988e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAccounts.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { useQuery } from '@tanstack/react-query'; - -import { accountsQueryKey } from '../helpers/query-client-keys'; -import { useBackgroundClient } from './useBackgroundClient'; - -export function useAccounts() { - const backgroundClient = useBackgroundClient(); - return useQuery({ - queryKey: accountsQueryKey, - queryFn: () => backgroundClient.getStoredEntities('accounts'), - gcTime: 30 * 1000, - staleTime: 15 * 1000, - refetchInterval: 30 * 1000, - meta: { skipPersistedCache: true }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useActiveAccount.ts b/apps/wallet/src/ui/app/hooks/useActiveAccount.ts deleted file mode 100644 index 8aa3018bdab16..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useActiveAccount.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMemo } from 'react'; - -import { useAccounts } from './useAccounts'; - -export function useActiveAccount() { - const { data: allAccounts } = useAccounts(); - return useMemo(() => { - if (!allAccounts) { - return null; - } - const selected = allAccounts.find(({ selected }) => selected); - if (selected) { - return selected; - } - return allAccounts[0] || null; - }, [allAccounts]); -} diff --git a/apps/wallet/src/ui/app/hooks/useActiveAddress.ts b/apps/wallet/src/ui/app/hooks/useActiveAddress.ts deleted file mode 100644 index 68f12884f6794..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useActiveAddress.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAccount } from './useActiveAccount'; - -export function useActiveAddress() { - return useActiveAccount()?.address || null; -} diff --git a/apps/wallet/src/ui/app/hooks/useAppDispatch.ts b/apps/wallet/src/ui/app/hooks/useAppDispatch.ts deleted file mode 100644 index fc88b52b1e39e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAppDispatch.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { AppDispatch } from '_store'; -import { useDispatch } from 'react-redux'; - -export default function useAppDispatch() { - return useDispatch(); -} diff --git a/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts b/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts deleted file mode 100644 index 44f8e1813179e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useFeatureIsOn } from '@growthbook/growthbook-react'; -import { normalizeSuiNSName } from '@mysten/sui/utils'; - -import { useResolveSuiNSName as useResolveSuiNSNameCore } from '../../../../../core'; - -export function useResolveSuiNSName(address?: string) { - const enableNewSuinsFormat = useFeatureIsOn('wallet-enable-new-suins-name-format'); - const { data } = useResolveSuiNSNameCore(address); - return data ? normalizeSuiNSName(data, enableNewSuinsFormat ? 'at' : 'dot') : undefined; -} diff --git a/apps/wallet/src/ui/app/hooks/useAppSelector.ts b/apps/wallet/src/ui/app/hooks/useAppSelector.ts deleted file mode 100644 index d09fac37a5d89..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAppSelector.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { RootState } from '_redux/RootReducer'; -import { useSelector } from 'react-redux'; -import type { TypedUseSelectorHook } from 'react-redux'; - -const useAppSelector: TypedUseSelectorHook = useSelector; - -export default useAppSelector; diff --git a/apps/wallet/src/ui/app/hooks/useAutoLockMinutes.ts b/apps/wallet/src/ui/app/hooks/useAutoLockMinutes.ts deleted file mode 100644 index 4301377935457..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAutoLockMinutes.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; -import { type z } from 'zod'; - -import { type zodSchema } from '../components/accounts/AutoLockSelector'; -import { useBackgroundClient } from './useBackgroundClient'; - -export type AutoLockInterval = z.infer['autoLock']['interval']; -export const autoLockMinutesQueryKey = ['get auto-lock minutes']; - -export function useAutoLockMinutes() { - const backgroundClient = useBackgroundClient(); - return useQuery({ - queryKey: autoLockMinutesQueryKey, - queryFn: () => backgroundClient.getAutoLockMinutes(), - refetchInterval: 15 * 1000, - meta: { - skipPersistedCache: true, - }, - }); -} - -const minutesOneDay = 60 * 24; -const minutesOneHour = 60; - -export function formatAutoLock(minutes: number | null) { - const { enabled, timer, interval } = parseAutoLock(minutes); - if (!enabled) { - return ''; - } - return `${timer} ${interval}${timer === 1 ? '' : 's'}`; -} - -export function parseAutoLock(minutes: number | null) { - let timer = minutes || 1; - const enabled = !!minutes; - let interval: AutoLockInterval = 'hour'; - if (enabled) { - if (minutes % minutesOneDay === 0) { - timer = Math.floor(minutes / minutesOneDay); - interval = 'day'; - } else if (minutes % minutesOneHour === 0) { - timer = Math.floor(minutes / minutesOneHour); - interval = 'hour'; - } else { - interval = 'minute'; - } - } - return { - enabled, - timer, - interval, - }; -} - -const intervalToMinutesMultiplier: Record = { - minute: 1, - hour: minutesOneHour, - day: minutesOneDay, -}; - -export function autoLockDataToMinutes({ - enabled, - timer, - interval, -}: { - enabled: boolean; - timer: number; - interval: AutoLockInterval; -}) { - if (!enabled) { - return null; - } - return intervalToMinutesMultiplier[interval] * (Number(timer) || 1); -} diff --git a/apps/wallet/src/ui/app/hooks/useAutoLockMinutesMutation.ts b/apps/wallet/src/ui/app/hooks/useAutoLockMinutesMutation.ts deleted file mode 100644 index f756360cd9076..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useAutoLockMinutesMutation.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMutation, useQueryClient } from '@tanstack/react-query'; - -import { autoLockMinutesQueryKey } from './useAutoLockMinutes'; -import { useBackgroundClient } from './useBackgroundClient'; - -export function useAutoLockMinutesMutation() { - const backgroundClient = useBackgroundClient(); - const queryClient = useQueryClient(); - return useMutation({ - mutationKey: ['set auto-lock minutes mutation'], - // minutes null disables the auto-lock - mutationFn: async ({ minutes }: { minutes: number | null }) => - backgroundClient.setAutoLockMinutes({ minutes }), - onSuccess: () => { - queryClient.invalidateQueries({ exact: true, queryKey: autoLockMinutesQueryKey }); - }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useBackgroundClient.ts b/apps/wallet/src/ui/app/hooks/useBackgroundClient.ts deleted file mode 100644 index f6e3f7a760695..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useBackgroundClient.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { thunkExtras } from '../redux/store/thunk-extras'; - -export function useBackgroundClient() { - return thunkExtras.background; -} diff --git a/apps/wallet/src/ui/app/hooks/useBlockedObjectList.ts b/apps/wallet/src/ui/app/hooks/useBlockedObjectList.ts deleted file mode 100644 index 93aaa61050aa4..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useBlockedObjectList.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { normalizeStructTag } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; - -import { useAppsBackend } from '../../../../../core'; - -export function useBlockedObjectList() { - const { request } = useAppsBackend(); - return useQuery({ - queryKey: ['apps-backend', 'guardian', 'object-list'], - queryFn: () => request<{ blocklist: string[] }>('guardian/object-list'), - select: (data) => data?.blocklist.map(normalizeStructTag) ?? [], - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useCoinMetadataOverride.ts b/apps/wallet/src/ui/app/hooks/useCoinMetadataOverride.ts deleted file mode 100644 index b6abab81e1282..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useCoinMetadataOverride.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { FEATURES } from '_shared/experimentation/features'; -import { useFeature } from '@growthbook/growthbook-react'; - -interface CoinMetadataOverride { - [coinType: string]: { - name?: string; - iconUrl?: string; - }; -} - -export function useCoinMetadataOverrides() { - const coinMetadataOverrides = useFeature( - FEATURES.TOKEN_METADATA_OVERRIDES, - ).value; - - return coinMetadataOverrides || {}; -} diff --git a/apps/wallet/src/ui/app/hooks/useCoinsReFetchingConfig.ts b/apps/wallet/src/ui/app/hooks/useCoinsReFetchingConfig.ts deleted file mode 100644 index 639c35c899926..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useCoinsReFetchingConfig.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { FEATURES } from '_src/shared/experimentation/features'; -import { useFeatureValue } from '@growthbook/growthbook-react'; - -export function useCoinsReFetchingConfig() { - const refetchInterval = useFeatureValue(FEATURES.WALLET_BALANCE_REFETCH_INTERVAL, 20_000); - return { - refetchInterval, - staleTime: 5_000, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useCopyToClipboard.ts b/apps/wallet/src/ui/app/hooks/useCopyToClipboard.ts deleted file mode 100644 index ceeb7e7736521..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useCopyToClipboard.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useCallback, type MouseEventHandler } from 'react'; -import { toast } from 'react-hot-toast'; - -export type CopyOptions = { - copySuccessMessage?: string; -}; - -export function useCopyToClipboard( - textToCopy: string, - { copySuccessMessage = 'Copied' }: CopyOptions = {}, -) { - return useCallback( - async (e) => { - e.stopPropagation(); - e.preventDefault(); - try { - await navigator.clipboard.writeText(textToCopy); - toast.success(copySuccessMessage); - } catch (e) { - // silence clipboard errors - } - }, - [textToCopy, copySuccessMessage], - ); -} diff --git a/apps/wallet/src/ui/app/hooks/useCountAccountByType.ts b/apps/wallet/src/ui/app/hooks/useCountAccountByType.ts deleted file mode 100644 index 191b9dcd3ff94..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useCountAccountByType.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type AccountType } from '_src/background/accounts/Account'; -import { type ZkLoginProvider } from '_src/background/accounts/zklogin/providers'; -import { isZkLoginAccountSerializedUI } from '_src/background/accounts/zklogin/ZkLoginAccount'; -import { useMemo } from 'react'; - -import { useAccounts } from './useAccounts'; - -export function useCountAccountsByType() { - const { data: accounts, isPending } = useAccounts(); - const countPerType = useMemo( - () => - accounts?.reduce< - Partial }>> - >((acc, anAccount) => { - acc[anAccount.type] = acc[anAccount.type] || { total: 0 }; - acc[anAccount.type]!.total++; - if (isZkLoginAccountSerializedUI(anAccount)) { - acc[anAccount.type]!.extra = - acc[anAccount.type]!.extra || ({} as Record); - acc[anAccount.type]!.extra![anAccount.provider] = - acc[anAccount.type]!.extra![anAccount.provider] || 0; - acc[anAccount.type]!.extra![anAccount.provider]++; - } - return acc; - }, {}) || {}, - [accounts], - ); - return { data: countPerType, isPending }; -} diff --git a/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts b/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts deleted file mode 100644 index 1e8848e3eb212..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli, type AddedAccountsProperties } from '_src/shared/analytics/ampli'; -import { useMutation } from '@tanstack/react-query'; - -import { - useAccountsFormContext, - type AccountsFormValues, -} from '../components/accounts/AccountsFormContext'; -import { useBackgroundClient } from './useBackgroundClient'; - -export type CreateType = NonNullable['type']; - -function validateAccountFormValues( - createType: T, - values: AccountsFormValues, - password?: string, -): values is Extract { - if (!values) { - throw new Error('Missing account data values'); - } - if (values.type !== createType) { - throw new Error('Account data values type mismatch'); - } - if (values.type !== 'zkLogin' && values.type !== 'mnemonic-derived' && !password) { - throw new Error('Missing password'); - } - return true; -} - -const createTypeToAmpliAccount: Record = { - zkLogin: 'Zklogin', - 'new-mnemonic': 'Derived', - 'import-mnemonic': 'Derived', - 'mnemonic-derived': 'Derived', - imported: 'Imported', - ledger: 'Ledger', - qredo: 'Qredo', -}; - -export function useCreateAccountsMutation() { - const backgroundClient = useBackgroundClient(); - const [accountsFormValuesRef, setAccountFormValues] = useAccountsFormContext(); - return useMutation({ - mutationKey: ['create accounts'], - mutationFn: async ({ type, password }: { type: CreateType; password?: string }) => { - let createdAccounts; - const accountsFormValues = accountsFormValuesRef.current; - if (type === 'zkLogin' && validateAccountFormValues(type, accountsFormValues)) { - createdAccounts = await backgroundClient.createAccounts(accountsFormValues); - } else if ( - (type === 'new-mnemonic' || type === 'import-mnemonic') && - validateAccountFormValues(type, accountsFormValues, password) - ) { - const accountSource = await backgroundClient.createMnemonicAccountSource({ - // validateAccountFormValues checks the password - password: password!, - entropy: 'entropy' in accountsFormValues ? accountsFormValues.entropy : undefined, - }); - await backgroundClient.unlockAccountSourceOrAccount({ - password, - id: accountSource.id, - }); - createdAccounts = await backgroundClient.createAccounts({ - type: 'mnemonic-derived', - sourceID: accountSource.id, - }); - } else if ( - type === 'mnemonic-derived' && - validateAccountFormValues(type, accountsFormValues, password) - ) { - if (password) { - await backgroundClient.unlockAccountSourceOrAccount({ - password, - id: accountsFormValues.sourceID, - }); - } - createdAccounts = await backgroundClient.createAccounts({ - type: 'mnemonic-derived', - sourceID: accountsFormValues.sourceID, - }); - } else if ( - type === 'imported' && - validateAccountFormValues(type, accountsFormValues, password) - ) { - createdAccounts = await backgroundClient.createAccounts({ - type: 'imported', - keyPair: accountsFormValues.keyPair, - password: password!, - }); - } else if ( - type === 'ledger' && - validateAccountFormValues(type, accountsFormValues, password) - ) { - createdAccounts = await backgroundClient.createAccounts({ - type: 'ledger', - accounts: accountsFormValues.accounts, - password: password!, - }); - } else if ( - type === 'qredo' && - validateAccountFormValues(type, accountsFormValues, password) - ) { - createdAccounts = await backgroundClient.acceptQredoConnection({ - qredoID: accountsFormValues.qredoID, - accounts: accountsFormValues.accounts, - password: password!, - }); - } else { - throw new Error(`Create accounts with type ${type} is not implemented yet`); - } - for (const aCreatedAccount of createdAccounts) { - await backgroundClient.unlockAccountSourceOrAccount({ - id: aCreatedAccount.id, - password, - }); - } - ampli.addedAccounts({ - accountType: createTypeToAmpliAccount[type], - numberOfAccounts: createdAccounts.length, - }); - setAccountFormValues(null); - const selectedAccount = createdAccounts[0]; - if (selectedAccount?.id) { - await backgroundClient.selectAccount(selectedAccount?.id); - } - return createdAccounts; - }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useExplorerLink.ts b/apps/wallet/src/ui/app/hooks/useExplorerLink.ts deleted file mode 100644 index 334aa0c763146..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useExplorerLink.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMemo } from 'react'; - -import { - getAddressUrl, - getObjectUrl, - getTransactionUrl, - getValidatorUrl, -} from '../components/explorer-link//Explorer'; -import { ExplorerLinkType } from '../components/explorer-link/ExplorerLinkType'; -import { useActiveAddress } from './useActiveAddress'; -import useAppSelector from './useAppSelector'; - -export type ExplorerLinkConfig = - | { - type: ExplorerLinkType.address; - address?: string; - useActiveAddress?: false; - } - | { - type: ExplorerLinkType.address; - useActiveAddress: true; - } - | { type: ExplorerLinkType.object; objectID: string; moduleName?: string } - | { type: ExplorerLinkType.transaction; transactionID: string } - | { type: ExplorerLinkType.validator; validator: string }; - -function useAddress(linkConfig: ExplorerLinkConfig) { - const { type } = linkConfig; - const isAddress = type === ExplorerLinkType.address; - const isProvidedAddress = isAddress && !linkConfig.useActiveAddress; - const activeAddress = useActiveAddress(); - return isProvidedAddress ? linkConfig.address : activeAddress; -} - -export function useExplorerLink(linkConfig: ExplorerLinkConfig) { - const { type } = linkConfig; - const address = useAddress(linkConfig); - const selectedApiEnv = useAppSelector(({ app }) => app.apiEnv); - const customRPC = useAppSelector(({ app }) => app.customRPC); - const objectID = type === ExplorerLinkType.object ? linkConfig.objectID : null; - const transactionID = type === ExplorerLinkType.transaction ? linkConfig.transactionID : null; - const validator = type === ExplorerLinkType.validator ? linkConfig.validator : null; - const moduleName = type === ExplorerLinkType.object ? linkConfig.moduleName : null; - - // fallback to localhost if customRPC is not set - const customRPCUrl = customRPC || 'http://localhost:3000/'; - return useMemo(() => { - if (!address) return null; - switch (type) { - case ExplorerLinkType.address: - return address && getAddressUrl(address, selectedApiEnv, customRPCUrl); - case ExplorerLinkType.object: - return objectID && getObjectUrl(objectID, selectedApiEnv, customRPCUrl, moduleName); - case ExplorerLinkType.transaction: - return transactionID && getTransactionUrl(transactionID, selectedApiEnv, customRPCUrl); - case ExplorerLinkType.validator: - return validator && getValidatorUrl(validator, selectedApiEnv, customRPCUrl); - } - }, [type, address, selectedApiEnv, customRPCUrl, moduleName, objectID, transactionID, validator]); -} diff --git a/apps/wallet/src/ui/app/hooks/useExportPassphraseMutation.tsx b/apps/wallet/src/ui/app/hooks/useExportPassphraseMutation.tsx deleted file mode 100644 index 8f032322ce831..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useExportPassphraseMutation.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type MethodPayload } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { entropyToMnemonic, toEntropy } from '_src/shared/utils/bip39'; -import { useMutation } from '@tanstack/react-query'; - -import { useBackgroundClient } from './useBackgroundClient'; - -export function useExportPassphraseMutation() { - const backgroundClient = useBackgroundClient(); - return useMutation({ - mutationKey: ['export passphrase'], - mutationFn: async (args: MethodPayload<'getAccountSourceEntropy'>['args']) => - entropyToMnemonic( - toEntropy((await backgroundClient.getAccountSourceEntropy(args)).entropy), - ).split(' '), - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useFileExtensionType.ts b/apps/wallet/src/ui/app/hooks/useFileExtensionType.ts deleted file mode 100644 index 4dd4cec9682b1..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useFileExtensionType.ts +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -type FileExtensionType = { - [key: string]: { - name: string; - type: string; - }; -}; - -// Soft file type detection. -// Returns the file type of the given file name. -// Temporary solution until we have a better way to detect file types. -// extentionType: FileExtensionType -// type?: 'image' | 'audio' | 'video'; -const FILE_EXTENSION_TYPE_MAP: FileExtensionType = { - jpeg: { - name: 'JPEG', - type: 'image', - }, - jpg: { - name: 'JPEG', - type: 'image', - }, - png: { - name: 'PNG', - type: 'image', - }, - gif: { - name: 'GIF', - type: 'image', - }, - bmp: { - name: 'BMP', - type: 'image', - }, - webp: { - name: 'WEBP', - type: 'image', - }, - svg: { - name: 'SVG', - type: 'image', - }, -}; - -/* -// TODO: extend this list with more file types. -const FILE_EXTENSION_TYPE_MAP_HEADERS: FileExtensionType = { - 'image/jpeg': { - name: 'JPEG', - type: 'image', - }, - 'image/png': { - name: 'PNG', - type: 'image', - }, - 'image/gif': { - name: 'GIF', - type: 'image', - }, - 'image/apng': { - name: 'APNG', - type: 'image', - }, - 'image/svg+xml': { - name: 'SVG', - type: 'image', - }, - 'image/webp': { - name: 'WEBP', - type: 'image', - }, - 'audio/wave': { - name: 'Wave', - type: 'audio', - }, - 'audio/wav': { - name: 'WEBP', - type: 'audio', - }, - 'audio/x-wav': { - name: 'WEBP', - type: 'audio', - }, - 'audio/x-pn-wav': { - name: 'WEBP', - type: 'audio', - }, -}; - -export const extractFileType = async (imgUrl: string) => { - return fetch(imgUrl) - .then((resp) => resp?.headers?.get('Content-Type') || false) - .catch((err) => { - return false; - }); -}; - */ -export default function useFileExtensionType(url: string) { - if (!url) return { name: '', type: '' }; - const fileType = url.split('.').pop() || ''; - return FILE_EXTENSION_TYPE_MAP[fileType] || { name: '', type: '' }; -} diff --git a/apps/wallet/src/ui/app/hooks/useFullscreenGuard.ts b/apps/wallet/src/ui/app/hooks/useFullscreenGuard.ts deleted file mode 100644 index 36bcafd1cf64a..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useFullscreenGuard.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { AppType } from '_redux/slices/app/AppType'; -import { openInNewTab } from '_shared/utils'; -import { useEffect, useRef } from 'react'; - -import useAppSelector from './useAppSelector'; - -export default function useFullscreenGuard(enabled: boolean) { - const appType = useAppSelector((state) => state.app.appType); - const isOpenTabInProgressRef = useRef(false); - useEffect(() => { - if (enabled && appType === AppType.popup && !isOpenTabInProgressRef.current) { - isOpenTabInProgressRef.current = true; - openInNewTab().finally(() => window.close()); - } - }, [appType, enabled]); - return !enabled && appType === AppType.unknown; -} diff --git a/apps/wallet/src/ui/app/hooks/useGetAllBalances.ts b/apps/wallet/src/ui/app/hooks/useGetAllBalances.ts deleted file mode 100644 index 94d5b10a62ffd..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetAllBalances.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useCoinsReFetchingConfig } from '_app/hooks/useCoinsReFetchingConfig'; -import { useSuiClientQuery } from '@mysten/dapp-kit'; - -export function useGetAllBalances(owner: string) { - const { staleTime, refetchInterval } = useCoinsReFetchingConfig(); - - return useSuiClientQuery( - 'getAllBalances', - { owner: owner! }, - { - enabled: !!owner, - refetchInterval, - staleTime, - }, - ); -} diff --git a/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts b/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts deleted file mode 100644 index 6e9608111669b..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useSuiClient } from '@mysten/dapp-kit'; -import type { CoinStruct, PaginatedCoins } from '@mysten/sui/client'; -import { useQuery } from '@tanstack/react-query'; - -const MAX_COINS_PER_REQUEST = 100; - -// Fetch all coins for an address, this will keep calling the API until all coins are fetched -export function useGetAllCoins(coinType: string, address?: string | null) { - const rpc = useSuiClient(); - return useQuery({ - queryKey: ['get-all-coins', address, coinType], - queryFn: async () => { - let cursor: string | undefined | null = null; - const allData: CoinStruct[] = []; - // keep fetching until cursor is null or undefined - do { - const { data, nextCursor }: PaginatedCoins = await rpc.getCoins({ - owner: address!, - coinType, - cursor, - limit: MAX_COINS_PER_REQUEST, - }); - if (!data || !data.length) { - break; - } - - allData.push(...data); - cursor = nextCursor; - } while (cursor); - - return allData; - }, - enabled: !!address, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useGetNFTMeta.ts b/apps/wallet/src/ui/app/hooks/useGetNFTMeta.ts deleted file mode 100644 index df29d812b5598..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetNFTMeta.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useGetObject } from '@mysten/core'; -import { useMemo } from 'react'; - -export type NFTMetadata = { - name: string | null; - description: string | null; - url: string; -}; - -export function useGetNFTMeta(objectID: string) { - const resp = useGetObject(objectID); - const nftMeta = useMemo(() => { - if (!resp.data) return null; - const display = resp.data.data?.display?.data; - if (!display) { - return null; - } - const { name, description, creator, image_url, link, project_url } = display; - return { - name: name || null, - description: description || null, - imageUrl: image_url || null, - link: link || null, - projectUrl: project_url || null, - creator: creator || null, - }; - }, [resp]); - return { - ...resp, - data: nftMeta, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useGetNFTs.ts b/apps/wallet/src/ui/app/hooks/useGetNFTs.ts deleted file mode 100644 index d11f7aa540083..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetNFTs.ts +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { hasDisplayData, isKioskOwnerToken, useGetOwnedObjects } from '@mysten/core'; -import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { type SuiObjectData } from '@mysten/sui/client'; -import { useMemo } from 'react'; - -import { useBuyNLargeAssets } from '../components/buynlarge/useBuyNLargeAssets'; -import { useHiddenAssets } from '../pages/home/hidden-assets/HiddenAssetsProvider'; - -type OwnedAssets = { - visual: SuiObjectData[]; - other: SuiObjectData[]; - hidden: SuiObjectData[]; -}; - -export enum AssetFilterTypes { - visual = 'visual', - other = 'other', -} - -export function useGetNFTs(address?: string | null) { - const kioskClient = useKioskClient(); - const bnl = useBuyNLargeAssets(); - const { - data, - isPending, - error, - isError, - isFetchingNextPage, - hasNextPage, - fetchNextPage, - isLoading, - } = useGetOwnedObjects( - address, - { - MatchNone: [ - { StructType: '0x2::coin::Coin' }, - ...(bnl - .filter((item) => !!item?.objectType) - .map((item) => ({ StructType: item?.objectType })) as { StructType: string }[]), - ], - }, - 50, - ); - const { hiddenAssetIds } = useHiddenAssets(); - - const assets = useMemo(() => { - const ownedAssets: OwnedAssets = { - visual: [], - other: [], - hidden: [], - }; - - const groupedAssets = data?.pages - .flatMap((page) => page.data) - .filter((asset) => !hiddenAssetIds.includes(asset.data?.objectId!)) - .reduce((acc, curr) => { - if (hasDisplayData(curr) || isKioskOwnerToken(kioskClient.network, curr)) - acc.visual.push(curr.data as SuiObjectData); - if (!hasDisplayData(curr)) acc.other.push(curr.data as SuiObjectData); - if (hiddenAssetIds.includes(curr.data?.objectId!)) - acc.hidden.push(curr.data as SuiObjectData); - return acc; - }, ownedAssets); - - bnl.forEach((item) => { - if (item?.asset?.data) { - groupedAssets?.visual.unshift(item.asset.data); - } - }); - - return groupedAssets; - }, [hiddenAssetIds, data?.pages, kioskClient.network, bnl]); - - return { - data: assets, - isLoading, - hasNextPage, - isFetchingNextPage, - fetchNextPage, - isPending: isPending, - isError: isError, - error, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useGetQredoTransaction.tsx b/apps/wallet/src/ui/app/hooks/useGetQredoTransaction.tsx deleted file mode 100644 index 0188d352473eb..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetQredoTransaction.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; - -import { useQredoAPI } from './useQredoAPI'; - -export function useGetQredoTransaction({ - qredoID, - qredoTransactionID, - forceDisabled, -}: { - qredoID?: string; - qredoTransactionID?: string; - forceDisabled?: boolean; -}) { - const [qredoAPI] = useQredoAPI(qredoID); - return useQuery({ - queryKey: ['get', 'qredo', 'transacion', qredoAPI, qredoID, qredoTransactionID], - queryFn: () => qredoAPI!.getTransaction(qredoTransactionID!), - enabled: !!(qredoAPI && qredoID && qredoTransactionID && !forceDisabled), - staleTime: 5000, - refetchInterval: 5000, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useGetQredoTransactions.tsx b/apps/wallet/src/ui/app/hooks/useGetQredoTransactions.tsx deleted file mode 100644 index 4a1a48dadf3d5..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetQredoTransactions.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type TransactionStatus } from '_src/shared/qredo-api'; -import { useQuery } from '@tanstack/react-query'; - -import { API_ENV_TO_QREDO_NETWORK } from '../QredoSigner'; -import { useActiveAddress } from './useActiveAddress'; -import useAppSelector from './useAppSelector'; -import { useQredoAPI } from './useQredoAPI'; - -export function useGetQredoTransactions({ - qredoID, - filterStatus, - forceDisabled, -}: { - qredoID?: string; - filterStatus?: TransactionStatus[]; - forceDisabled?: boolean; -}) { - const [qredoAPI] = useQredoAPI(qredoID); - const apiEnv = useAppSelector(({ app: { apiEnv } }) => apiEnv); - const networkName = API_ENV_TO_QREDO_NETWORK[apiEnv] || null; - const activeAddress = useActiveAddress(); - return useQuery({ - queryKey: [ - 'get', - 'qredo', - 'transacions', - qredoAPI, - qredoID, - networkName, - activeAddress, - filterStatus, - ], - queryFn: () => - qredoAPI!.getTransactions({ - network: networkName!, - address: activeAddress!, - }), - select: ({ list }) => - list.filter(({ status }) => !filterStatus?.length || filterStatus.includes(status)), - enabled: !!(qredoAPI && qredoID && networkName && activeAddress && !forceDisabled), - staleTime: 5000, - refetchInterval: 5000, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts b/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts deleted file mode 100644 index aa42cc850e1d4..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { getAmount } from '_helpers'; -import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -export function useGetTransferAmount({ - txn, - activeAddress, -}: { - txn: SuiTransactionBlockResponse; - activeAddress: string; -}) { - const { effects, events } = txn; - // const { coins } = getEventsSummary(events!, activeAddress); - - const suiTransfer = useMemo(() => { - const txdetails = txn.transaction?.data.transaction!; - return getAmount(txdetails, effects!, events!)?.map( - ({ amount, coinType, recipientAddress }) => { - return { - amount: amount || 0, - coinType: coinType || SUI_TYPE_ARG, - receiverAddress: recipientAddress, - }; - }, - ); - }, [txn, effects, events]); - - // MUSTFIX(chris) - // const transferAmount = useMemo(() => { - // return suiTransfer?.length - // ? suiTransfer - // : coins.filter( - // ({ receiverAddress }) => receiverAddress === activeAddress - // ); - // }, [suiTransfer, coins, activeAddress]); - - // return suiTransfer ?? transferAmount; - return suiTransfer; -} diff --git a/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts b/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts deleted file mode 100644 index 45f5607cc7800..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { getAmount } from '_helpers'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { useMemo } from 'react'; - -type Props = { - txn: SuiTransactionBlockResponse; - address: string; -}; - -export function useGetTxnRecipientAddress({ txn, address }: Props) { - const events = txn.events!; - - // const eventsSummary = useMemo(() => { - // const { coins } = getEventsSummary(events, address); - // return coins; - // }, [events, address]); - - const transaction = txn.transaction?.data.transaction!; - const amountByRecipient = getAmount(transaction, txn.effects!, events); - - const recipientAddress = useMemo(() => { - const transferObjectRecipientAddress = - amountByRecipient && - amountByRecipient?.find(({ recipientAddress }) => recipientAddress !== address) - ?.recipientAddress; - // MUSTFIX(chris) - // const receiverAddr = - // eventsSummary && - // eventsSummary.find( - // ({ receiverAddress }) => receiverAddress !== address - // )?.receiverAddress; - - return null ?? transferObjectRecipientAddress ?? txn.transaction?.data.sender; - }, [address, amountByRecipient, txn]); - // }, [address, amountByRecipient, eventsSummary, txn]); - - return recipientAddress; -} diff --git a/apps/wallet/src/ui/app/hooks/useInitialPageView.ts b/apps/wallet/src/ui/app/hooks/useInitialPageView.ts deleted file mode 100644 index c365bf18f3c8e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useInitialPageView.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import { useEffect } from 'react'; -import { useLocation } from 'react-router-dom'; -import Browser from 'webextension-polyfill'; - -import { AppType } from '../redux/slices/app/AppType'; -import { useActiveAccount } from './useActiveAccount'; -import useAppSelector from './useAppSelector'; - -export function useInitialPageView() { - const activeAccount = useActiveAccount(); - const location = useLocation(); - const { apiEnv, customRPC, activeOrigin, appType } = useAppSelector((state) => state.app); - const activeNetwork = customRPC && apiEnv === 'customRPC' ? customRPC : apiEnv.toUpperCase(); - const isFullScreen = appType === AppType.fullscreen; - - useEffect(() => { - ampli.identify(undefined, { - activeNetwork, - activeAccountType: activeAccount?.type, - activeOrigin: activeOrigin || undefined, - pagePath: location.pathname, - pagePathFragment: `${location.pathname}${location.search}${location.hash}`, - walletAppMode: isFullScreen ? 'Fullscreen' : 'Pop-up', - walletVersion: Browser.runtime.getManifest().version, - }); - }, [activeAccount?.type, activeNetwork, activeOrigin, isFullScreen, location]); - - useEffect(() => { - ampli.openedWalletExtension(); - }, []); -} diff --git a/apps/wallet/src/ui/app/hooks/useInitializedGuard.ts b/apps/wallet/src/ui/app/hooks/useInitializedGuard.ts deleted file mode 100644 index cf28fa83518db..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useInitializedGuard.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { useAccounts } from './useAccounts'; -import { useRestrictedGuard } from './useRestrictedGuard'; - -export default function useInitializedGuard(initializedRequired: boolean, enabled = true) { - const restricted = useRestrictedGuard(); - const { data: allAccounts, isPending } = useAccounts(); - const isInitialized = !!allAccounts?.length; - const navigate = useNavigate(); - const guardAct = !restricted && !isPending && initializedRequired !== isInitialized && enabled; - useEffect(() => { - if (guardAct) { - navigate(isInitialized ? '/' : '/accounts/welcome', { replace: true }); - } - }, [guardAct, isInitialized, navigate]); - return isPending || guardAct; -} diff --git a/apps/wallet/src/ui/app/hooks/useIsWalletDefiEnabled.ts b/apps/wallet/src/ui/app/hooks/useIsWalletDefiEnabled.ts deleted file mode 100644 index d35ab3bc035ff..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useIsWalletDefiEnabled.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import useAppSelector from '_app/hooks/useAppSelector'; -import { API_ENV } from '_shared/api-env'; -import { FEATURES } from '_shared/experimentation/features'; -import { useFeature } from '@growthbook/growthbook-react'; - -export function useIsWalletDefiEnabled() { - const isDefiWalletEnabled = useFeature(FEATURES.WALLET_DEFI).value; - const { apiEnv } = useAppSelector((state) => state.app); - - return apiEnv === API_ENV.mainnet && isDefiWalletEnabled; -} diff --git a/apps/wallet/src/ui/app/hooks/useMediaUrl.ts b/apps/wallet/src/ui/app/hooks/useMediaUrl.ts deleted file mode 100644 index 407ea1164d609..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useMediaUrl.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiParsedData } from '@mysten/sui/client'; -import { useMemo } from 'react'; - -export const parseIpfsUrl = (ipfsUrl: string) => - ipfsUrl.replace(/^ipfs:\/\//, 'https://ipfs.io/ipfs/'); - -export default function useMediaUrl(objData: SuiParsedData | null) { - const { fields } = - ((objData?.dataType === 'moveObject' && objData) as { - fields: { url?: string; metadata?: { fields: { url: string } } }; - }) || {}; - return useMemo(() => { - if (fields) { - const mediaUrl = fields.url || fields.metadata?.fields.url; - if (typeof mediaUrl === 'string') { - return parseIpfsUrl(mediaUrl); - } - } - return null; - }, [fields]); -} diff --git a/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts b/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts deleted file mode 100644 index 67973a7548913..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiObjectData } from '@mysten/sui/client'; - -import useFileExtensionType from './useFileExtensionType'; -import useMediaUrl from './useMediaUrl'; - -export default function useNFTBasicData(nftObj: SuiObjectData | null) { - const nftObjectID = nftObj?.objectId || null; - const filePath = useMediaUrl(nftObj?.content || null); - let objType = null; - let nftFields = null; - if (nftObj && nftObj.content?.dataType === 'moveObject') { - objType = nftObj.content?.type; - nftFields = nftObj?.content?.dataType === 'moveObject' ? nftObj.content.fields : null; - } - const fileExtensionType = useFileExtensionType(filePath || ''); - return { - nftObjectID, - filePath, - nftFields, - fileExtensionType, - objType, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useOnClickOutside.ts b/apps/wallet/src/ui/app/hooks/useOnClickOutside.ts deleted file mode 100644 index 3c4e0d55e0892..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useOnClickOutside.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; -import type { RefObject } from 'react'; - -type Event = MouseEvent | TouchEvent; - -const useOnClickOutside = ( - ref: RefObject, - handler: (event: Event) => void, -) => { - useEffect(() => { - const listener = (event: Event) => { - const el = ref?.current; - if (!el || el.contains(event?.target as Node)) { - return; - } - - handler(event); // Call the handler only if the click is outside of the element passed. - }; - - document.addEventListener('click', listener, true); - document.addEventListener('touchstart', listener, true); - - return () => { - document.removeEventListener('click', listener, true); - document.removeEventListener('touchstart', listener, true); - }; - }, [ref, handler]); // Reload only if ref or handler changes -}; - -export default useOnClickOutside; diff --git a/apps/wallet/src/ui/app/hooks/useOnKeyboardEvent.ts b/apps/wallet/src/ui/app/hooks/useOnKeyboardEvent.ts deleted file mode 100644 index ce41e34feb982..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useOnKeyboardEvent.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; - -function useOnKeyboardEvent( - eventType: K, - keys: string[], - handler: (e: KeyboardEvent) => void, - enabled = true, -) { - useEffect(() => { - if (enabled) { - const listener = (e: KeyboardEvent) => { - if (keys.includes(e.key)) { - handler(e); - } - }; - - document.addEventListener(eventType, listener); - - return () => { - document.removeEventListener(eventType, listener); - }; - } - }, [eventType, keys, handler, enabled]); -} - -export default useOnKeyboardEvent; diff --git a/apps/wallet/src/ui/app/hooks/useOwnedNFT.ts b/apps/wallet/src/ui/app/hooks/useOwnedNFT.ts deleted file mode 100644 index 3acfc1d797a94..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useOwnedNFT.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useGetKioskContents, useGetObject } from '@mysten/core'; -import { useMemo } from 'react'; - -export function useOwnedNFT(nftObjectId: string | null, address: string | null) { - const data = useGetObject(nftObjectId); - const { data: kioskData, isFetching: areKioskContentsLoading } = useGetKioskContents(address); - const { data: objectData, isPending } = data; - - const objectDetails = useMemo(() => { - if (!objectData || !objectData.data || !address) return null; - const ownedKioskObjectIds = kioskData?.list.map(({ data }) => data?.objectId) || []; - const objectOwner = objectData.data.owner; - const data = - ownedKioskObjectIds.includes(objectData.data.objectId) || - (objectOwner && - objectOwner !== 'Immutable' && - 'AddressOwner' in objectOwner && - objectOwner.AddressOwner === address) - ? objectData.data - : null; - return data; - }, [address, objectData, kioskData]); - - return { ...data, isPending: isPending || areKioskContentsLoading, data: objectDetails }; -} diff --git a/apps/wallet/src/ui/app/hooks/usePinnedCoinTypes.ts b/apps/wallet/src/ui/app/hooks/usePinnedCoinTypes.ts deleted file mode 100644 index c4dc9991e04d3..0000000000000 --- a/apps/wallet/src/ui/app/hooks/usePinnedCoinTypes.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useCoinsStore } from '_app/zustand/coins'; -import { get } from 'idb-keyval'; -import { useCallback, useEffect } from 'react'; - -import { useRecognizedPackages } from './useRecognizedPackages'; - -const PINNED_COIN_TYPES = 'pinned-coin-types'; - -export function usePinnedCoinTypes() { - const coinsStore = useCoinsStore(); - const setPinnedCoinTypes = coinsStore.setPinnedCoinTypes; - const internalPinnedCoinTypes = coinsStore.pinnedCoinTypes; - const recognizedPackages = useRecognizedPackages(); - - useEffect(() => { - (async () => { - const pinnedCoins = await get(PINNED_COIN_TYPES); - - if (pinnedCoins) { - const filteredPinnedCoins = pinnedCoins.filter( - (coinType) => !recognizedPackages.includes(coinType.split('::')[0]), - ); - setPinnedCoinTypes(PINNED_COIN_TYPES, filteredPinnedCoins); - } - })(); - }, [recognizedPackages, setPinnedCoinTypes]); - - const pinCoinType = useCallback( - async (newCoinType: string) => { - if (internalPinnedCoinTypes.find((coinType) => coinType === newCoinType)) return; - - const newPinnedCoinTypes = [...internalPinnedCoinTypes, newCoinType]; - setPinnedCoinTypes(PINNED_COIN_TYPES, newPinnedCoinTypes); - }, - [internalPinnedCoinTypes, setPinnedCoinTypes], - ); - - const unpinCoinType = useCallback( - async (removeCoinType: string) => { - const newPinnedCoinTypes = internalPinnedCoinTypes.filter( - (coinType) => coinType !== removeCoinType, - ); - setPinnedCoinTypes(PINNED_COIN_TYPES, newPinnedCoinTypes); - }, - [internalPinnedCoinTypes, setPinnedCoinTypes], - ); - - return [internalPinnedCoinTypes, { pinCoinType, unpinCoinType }] as const; -} diff --git a/apps/wallet/src/ui/app/hooks/useQredoAPI.ts b/apps/wallet/src/ui/app/hooks/useQredoAPI.ts deleted file mode 100644 index 1ca52ba703d37..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useQredoAPI.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { QredoAPI } from '_src/shared/qredo-api'; -import { useEffect, useState } from 'react'; - -import { useBackgroundClient } from './useBackgroundClient'; -import { useQredoInfo } from './useQredoInfo'; - -const API_INSTANCES: Record = {}; - -export function useQredoAPI(qredoID?: string) { - const backgroundClient = useBackgroundClient(); - const { data, isPending, error } = useQredoInfo(qredoID || null); - const [api, setAPI] = useState(() => (qredoID && API_INSTANCES[qredoID]) || null); - useEffect(() => { - if (data?.qredoInfo?.apiUrl && data?.qredoInfo?.accessToken && qredoID) { - const instance = API_INSTANCES[qredoID]; - if (instance && instance.accessToken !== data.qredoInfo.accessToken) { - instance.accessToken = data.qredoInfo.accessToken; - } else if (!instance) { - API_INSTANCES[qredoID] = new QredoAPI(qredoID, data.qredoInfo.apiUrl, { - accessTokenRenewalFN: async (qredoID) => - (await backgroundClient.getQredoConnectionInfo(qredoID, true)).qredoInfo?.accessToken || - null, - accessToken: data.qredoInfo.accessToken, - }); - } - } - setAPI((qredoID && API_INSTANCES[qredoID]) || null); - }, [backgroundClient, data?.qredoInfo?.apiUrl, data?.qredoInfo?.accessToken, qredoID]); - return [api, isPending, error] as const; -} diff --git a/apps/wallet/src/ui/app/hooks/useQredoInfo.ts b/apps/wallet/src/ui/app/hooks/useQredoInfo.ts deleted file mode 100644 index d4704a6ca70a3..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useQredoInfo.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; - -import { useBackgroundClient } from './useBackgroundClient'; - -export function useQredoInfo(qredoID: string | null) { - const backgroundClient = useBackgroundClient(); - return useQuery({ - queryKey: ['qredo', 'info', qredoID], - queryFn: async () => backgroundClient.getQredoConnectionInfo(qredoID!), - enabled: !!qredoID, - staleTime: 0, - refetchInterval: 1000, - meta: { skipPersistedCache: true }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useQredoTransaction.tsx b/apps/wallet/src/ui/app/hooks/useQredoTransaction.tsx deleted file mode 100644 index c8f3f0c97e68f..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useQredoTransaction.tsx +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect, useState } from 'react'; -import { v4 as uuidV4 } from 'uuid'; - -import Alert from '../components/alert'; -import LoadingIndicator from '../components/loading/LoadingIndicator'; -import { QredoEvents, type QredoEventsType } from '../QredoSigner'; -import { Button } from '../shared/ButtonUI'; -import { Dialog, DialogContent } from '../shared/Dialog'; -import { Heading } from '../shared/heading'; -import { Text } from '../shared/text'; - -export function useQredoTransaction(preventModalDismiss?: boolean) { - const [clientIdentifier, setClientIdentifier] = useState(() => uuidV4()); - const [qredoTransactionID, setQredoTransactionID] = useState(null); - const notificationModal = ( - { - if (!open && !preventModalDismiss) { - QredoEvents.emit('clientIgnoredUpdates', { - clientIdentifier, - }); - setQredoTransactionID(null); - } - }} - > - -
    - {preventModalDismiss ? ( - Don't close this window until the transaction is completed - ) : null} -
    -
    - -
    - - Awaiting transaction approval in the Qredo app - - - Check your Qredo app for status. Once all required custody approvals have been performed - the transaction will complete. - - {!preventModalDismiss ? ( -
    - -
    - ); - useEffect(() => { - function qredoTransactionCreated(event: QredoEventsType['qredoTransactionCreated']) { - if (event.clientIdentifier === clientIdentifier) { - setQredoTransactionID(event.qredoTransaction.txID); - } - } - function qredoTransactionComplete(event: QredoEventsType['qredoActionDone']) { - if (event.clientIdentifier === clientIdentifier) { - setQredoTransactionID(null); - setClientIdentifier(uuidV4()); - } - } - QredoEvents.on('qredoTransactionCreated', qredoTransactionCreated); - QredoEvents.on('qredoActionDone', qredoTransactionComplete); - return () => { - QredoEvents.off('qredoTransactionCreated', qredoTransactionCreated); - QredoEvents.off('qredoActionDone', qredoTransactionComplete); - QredoEvents.emit('clientIgnoredUpdates', { clientIdentifier }); - }; - }, [clientIdentifier]); - return { - clientIdentifier, - notificationModal, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts b/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts deleted file mode 100644 index f493a18fcb61e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { FEATURES } from '_src/shared/experimentation/features'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { useQuery } from '@tanstack/react-query'; - -export function useQueryTransactionsByAddress(address: string | null) { - const rpc = useSuiClient(); - const refetchInterval = useFeatureValue(FEATURES.WALLET_ACTIVITY_REFETCH_INTERVAL, 20_000); - - return useQuery({ - queryKey: ['transactions-by-address', address], - queryFn: async () => { - // combine from and to transactions - const [txnIds, fromTxnIds] = await Promise.all([ - rpc.queryTransactionBlocks({ - filter: { - ToAddress: address!, - }, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }), - rpc.queryTransactionBlocks({ - filter: { - FromAddress: address!, - }, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }), - ]); - - const inserted = new Map(); - const uniqueList: SuiTransactionBlockResponse[] = []; - - [...txnIds.data, ...fromTxnIds.data] - .sort((a, b) => Number(b.timestampMs ?? 0) - Number(a.timestampMs ?? 0)) - .forEach((txb) => { - if (inserted.get(txb.digest)) return; - uniqueList.push(txb); - inserted.set(txb.digest, true); - }); - - return uniqueList; - }, - enabled: !!address, - staleTime: 10 * 1000, - refetchInterval, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts b/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts deleted file mode 100644 index f66a38d5dcad6..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV } from '_src/shared/api-env'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { SUI_FRAMEWORK_ADDRESS, SUI_SYSTEM_ADDRESS } from '@mysten/sui/utils'; - -import useAppSelector from './useAppSelector'; - -const DEFAULT_RECOGNIZED_PACKAGES = [SUI_FRAMEWORK_ADDRESS, SUI_SYSTEM_ADDRESS]; - -export function useRecognizedPackages() { - const apiEnv = useAppSelector((app) => app.app.apiEnv); - const recognizedPackages = useFeatureValue('recognized-packages', DEFAULT_RECOGNIZED_PACKAGES); - - // Our recognized package list is currently only available on mainnet - return apiEnv === API_ENV.mainnet ? recognizedPackages : DEFAULT_RECOGNIZED_PACKAGES; -} diff --git a/apps/wallet/src/ui/app/hooks/useRecoveryDataMutation.ts b/apps/wallet/src/ui/app/hooks/useRecoveryDataMutation.ts deleted file mode 100644 index 72932ecde451d..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useRecoveryDataMutation.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type PasswordRecoveryData } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { useMutation } from '@tanstack/react-query'; - -import { useForgotPasswordContext } from '../pages/accounts/forgot-password/ForgotPasswordPage'; -import { useBackgroundClient } from './useBackgroundClient'; - -export function useRecoveryDataMutation() { - const backgroundClient = useBackgroundClient(); - const { add } = useForgotPasswordContext(); - return useMutation({ - mutationKey: ['add recovery data'], - mutationFn: async (data: PasswordRecoveryData) => { - await backgroundClient.verifyPasswordRecoveryData({ data }); - add(data); - }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useResetPasswordMutation.ts b/apps/wallet/src/ui/app/hooks/useResetPasswordMutation.ts deleted file mode 100644 index 53f6d9c0dbbe8..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useResetPasswordMutation.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMutation } from '@tanstack/react-query'; - -import { type BackgroundClient } from '../background-client'; -import { useBackgroundClient } from './useBackgroundClient'; - -export function useResetPasswordMutation() { - const backgroundClient = useBackgroundClient(); - return useMutation({ - mutationKey: ['reset wallet password'], - mutationFn: async (...args: Parameters) => { - return await backgroundClient.resetPassword(...args); - }, - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useResolveVideo.ts b/apps/wallet/src/ui/app/hooks/useResolveVideo.ts deleted file mode 100644 index 99f01ce8be090..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useResolveVideo.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SuiObjectResponse } from '@mysten/sui/client'; - -import { useRecognizedPackages } from './useRecognizedPackages'; - -export function useResolveVideo(object?: SuiObjectResponse | null) { - const recognizedPackages = useRecognizedPackages(); - - if (!object) return null; - - const objectType = - object.data?.type ?? - (object?.data?.content?.dataType === 'package' ? 'package' : object?.data?.content?.type) ?? - null; - const isRecognized = objectType && recognizedPackages.includes(objectType.split('::')[0]); - - if (!isRecognized) return null; - - const display = object.data?.display?.data; - - return display?.video_url; -} diff --git a/apps/wallet/src/ui/app/hooks/useRestrictedGuard.ts b/apps/wallet/src/ui/app/hooks/useRestrictedGuard.ts deleted file mode 100644 index a685995be804f..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useRestrictedGuard.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; -import { useEffect } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; - -export const RESTRICTED_ERROR = { - status: 403, - body: 'error code: 1020', -}; - -export function useRestrictedGuard() { - const navigate = useNavigate(); - const location = useLocation(); - - const { data } = useQuery({ - queryKey: ['restricted-guard'], - queryFn: async () => { - // NOTE: We use fetch directly here instead of the RPC layer because we don't want this instrumented, - // and we also need to work with the response object directly. - const res = await fetch('https://wallet-rpc.testnet.sui.io/', { - method: 'POST', - body: JSON.stringify({ - id: 1, - method: 'sui_getLatestCheckpointSequenceNumber', - jsonrpc: '2.0', - params: [], - }), - headers: { - // Resetting accept makes the response non-HTML - accept: '', - 'content-type': 'application/json', - }, - }); - - if (res.status === RESTRICTED_ERROR.status) { - const body = await res.text(); - return { restricted: body === RESTRICTED_ERROR.body }; - } - - return { restricted: false }; - }, - gcTime: 0, - retry: 0, - }); - - useEffect(() => { - if (!data) return; - if (data.restricted && location.pathname !== '/restricted') { - navigate('/restricted', { replace: true }); - } else if (!data.restricted && location.pathname === '/restricted') { - // If access is not restricted, but the user is on the restricted page, then we want to get them out of there: - navigate('/', { replace: true }); - } - }, [navigate, data, location.pathname]); - - return data?.restricted ?? false; -} diff --git a/apps/wallet/src/ui/app/hooks/useSigner.ts b/apps/wallet/src/ui/app/hooks/useSigner.ts deleted file mode 100644 index 22b470c305519..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useSigner.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { isLedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount'; -import { isQredoAccountSerializedUI } from '_src/background/accounts/QredoAccount'; -import { useSuiClient } from '@mysten/dapp-kit'; - -import { walletApiProvider } from '../ApiProvider'; -import { useSuiLedgerClient } from '../components/ledger/SuiLedgerClientProvider'; -import { LedgerSigner } from '../LedgerSigner'; -import { QredoSigner } from '../QredoSigner'; -import { type WalletSigner } from '../WalletSigner'; -import useAppSelector from './useAppSelector'; -import { useBackgroundClient } from './useBackgroundClient'; -import { useQredoAPI } from './useQredoAPI'; - -export function useSigner(account: SerializedUIAccount | null): WalletSigner | null { - const { connectToLedger } = useSuiLedgerClient(); - const api = useSuiClient(); - const background = useBackgroundClient(); - const [qredoAPI] = useQredoAPI( - account && !account?.isLocked && isQredoAccountSerializedUI(account) - ? account.sourceID - : undefined, - ); - const networkName = useAppSelector(({ app: { apiEnv } }) => apiEnv); - if (!account) { - return null; - } - if (isLedgerAccountSerializedUI(account)) { - return new LedgerSigner(connectToLedger, account.derivationPath, api); - } - if (isQredoAccountSerializedUI(account)) { - return qredoAPI ? new QredoSigner(api, account, qredoAPI, networkName) : null; - } - return walletApiProvider.getSignerInstance(account, background); -} diff --git a/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts b/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts deleted file mode 100644 index 3f5c543dfb696..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { usePinnedCoinTypes } from '_app/hooks/usePinnedCoinTypes'; -import { useRecognizedPackages } from '_app/hooks/useRecognizedPackages'; -import { type CoinBalance as CoinBalanceType } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -function sortCoins(balances: CoinBalanceType[]) { - return balances.sort((a, b) => { - if (a.coinType === SUI_TYPE_ARG) { - return -1; - } - - return a.coinType.toLowerCase().localeCompare(b.coinType.toLowerCase()); - }); -} - -export function useSortedCoinsByCategories(coinBalances: CoinBalanceType[]) { - const recognizedPackages = useRecognizedPackages(); - const [pinnedCoinTypes] = usePinnedCoinTypes(); - - return useMemo(() => { - const reducedCoinBalances = coinBalances?.reduce( - (acc, coinBalance) => { - if (recognizedPackages.includes(coinBalance.coinType.split('::')[0])) { - acc.recognized.push(coinBalance); - } else if (pinnedCoinTypes.includes(coinBalance.coinType)) { - acc.pinned.push(coinBalance); - } else { - acc.unrecognized.push(coinBalance); - } - return acc; - }, - { - recognized: [] as CoinBalanceType[], - pinned: [] as CoinBalanceType[], - unrecognized: [] as CoinBalanceType[], - }, - ) ?? { recognized: [], pinned: [], unrecognized: [] }; - - return { - recognized: sortCoins(reducedCoinBalances.recognized), - pinned: sortCoins(reducedCoinBalances.pinned), - unrecognized: sortCoins(reducedCoinBalances.unrecognized), - }; - }, [coinBalances, recognizedPackages, pinnedCoinTypes]); -} diff --git a/apps/wallet/src/ui/app/hooks/useStorageMigrationStatus.ts b/apps/wallet/src/ui/app/hooks/useStorageMigrationStatus.ts deleted file mode 100644 index ad8e2d7d08fdb..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useStorageMigrationStatus.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useQuery } from '@tanstack/react-query'; -import { useEffect, useState } from 'react'; - -import { useBackgroundClient } from './useBackgroundClient'; - -export function useStorageMigrationStatus() { - const [enabled, setEnabled] = useState(true); - const backgroundClient = useBackgroundClient(); - const response = useQuery({ - queryKey: ['storage migration status'], - queryFn: () => backgroundClient.getStorageMigrationStatus(), - refetchInterval: 1000, - enabled, - meta: { skipPersistedCache: true }, - }); - useEffect(() => { - if (response.data === 'ready') { - setEnabled(false); - } - }, [response.data]); - return response; -} diff --git a/apps/wallet/src/ui/app/hooks/useSupportedCoins.ts b/apps/wallet/src/ui/app/hooks/useSupportedCoins.ts deleted file mode 100644 index 65d8ee279c0ab..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useSupportedCoins.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useAppsBackend } from '@mysten/core'; -import { useQuery } from '@tanstack/react-query'; - -export function useSupportedCoins() { - const { request } = useAppsBackend(); - - return useQuery({ - queryKey: ['supported-coins-apps-backend'], - queryFn: async () => request<{ supported: string[] }>('swap/coins'), - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useTransactionData.ts b/apps/wallet/src/ui/app/hooks/useTransactionData.ts deleted file mode 100644 index ccb3d61074311..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useTransactionData.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useFormatCoin } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { Transaction } from '@mysten/sui/transactions'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; - -export function useTransactionData(sender?: string | null, transaction?: Transaction | null) { - const client = useSuiClient(); - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ['transaction-data', transaction?.serialize()], - queryFn: async () => { - const clonedTransaction = Transaction.from(transaction!); - if (sender) { - clonedTransaction.setSenderIfNotSet(sender); - } - // Build the transaction to bytes, which will ensure that the transaction data is fully populated: - await clonedTransaction!.build({ client }); - return clonedTransaction!.getData(); - }, - enabled: !!transaction, - }); -} - -export function useTransactionGasBudget(sender?: string | null, transaction?: Transaction | null) { - const { data, ...rest } = useTransactionData(sender, transaction); - - const [formattedGas] = useFormatCoin(data?.gasData.budget, SUI_TYPE_ARG); - - return { - data: formattedGas, - ...rest, - }; -} diff --git a/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts b/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts deleted file mode 100644 index 0f75567bded2b..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Transaction } from '@mysten/sui/transactions'; -import { useQuery } from '@tanstack/react-query'; - -import { useAccountByAddress } from './useAccountByAddress'; -import { useSigner } from './useSigner'; - -export function useTransactionDryRun(sender: string | undefined, transactionBlock: Transaction) { - const { data: account } = useAccountByAddress(sender); - const signer = useSigner(account || null); - const response = useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ['dryRunTransaction', transactionBlock.serialize()], - queryFn: () => { - return signer!.dryRunTransactionBlock({ transactionBlock }); - }, - enabled: !!signer, - }); - return response; -} diff --git a/apps/wallet/src/ui/app/hooks/useUnlockMutation.ts b/apps/wallet/src/ui/app/hooks/useUnlockMutation.ts deleted file mode 100644 index 73763ea331c43..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useUnlockMutation.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMutation } from '@tanstack/react-query'; - -import { type BackgroundClient } from '../background-client'; -import { useBackgroundClient } from './useBackgroundClient'; - -export function useUnlockMutation() { - const backgroundClient = useBackgroundClient(); - return useMutation({ - mutationKey: ['accounts', 'unlock', 'account source or account'], - mutationFn: async (inputs: Parameters['0']) => - backgroundClient.unlockAccountSourceOrAccount(inputs), - }); -} diff --git a/apps/wallet/src/ui/app/hooks/useUnlockedGuard.ts b/apps/wallet/src/ui/app/hooks/useUnlockedGuard.ts deleted file mode 100644 index 556f7a5575044..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useUnlockedGuard.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { useAccounts } from '../hooks/useAccounts'; -import { useActiveAccount } from '../hooks/useActiveAccount'; - -export function useUnlockedGuard() { - const navigate = useNavigate(); - const { data: allAccounts, isPending: isAccountsLoading } = useAccounts(); - const activeAccount = useActiveAccount(); - const loading = isAccountsLoading || !activeAccount; - const isInitialized = !!allAccounts?.length; - const isLocked = !!activeAccount?.isLocked; - const guardAct = !loading && isInitialized && isLocked; - useEffect(() => { - if (guardAct) { - navigate(`/tokens`, { replace: true }); - } - }, [guardAct, navigate]); - - return loading || guardAct; -} diff --git a/apps/wallet/src/ui/app/hooks/useValidSwapTokensList.ts b/apps/wallet/src/ui/app/hooks/useValidSwapTokensList.ts deleted file mode 100644 index fea5757201d5e..0000000000000 --- a/apps/wallet/src/ui/app/hooks/useValidSwapTokensList.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import { useGetAllBalances } from '_app/hooks/useGetAllBalances'; -import { useRecognizedPackages } from '_app/hooks/useRecognizedPackages'; -import { useSupportedCoins } from '_app/hooks/useSupportedCoins'; -import { type CoinBalance } from '@mysten/sui/client'; -import { - normalizeStructTag, - normalizeSuiObjectId, - parseStructTag, - SUI_TYPE_ARG, -} from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -export function filterTokenBalances(tokens: CoinBalance[]) { - return tokens.filter( - (token) => Number(token.totalBalance) > 0 || token.coinType === SUI_TYPE_ARG, - ); -} - -export function useValidSwapTokensList() { - const address = useActiveAddress(); - const { data, isLoading: isSupportedCoinsLoading } = useSupportedCoins(); - const { data: rawCoinBalances, isLoading: isGetAllBalancesLoading } = useGetAllBalances( - address || '', - ); - const packages = useRecognizedPackages(); - const normalizedPackages = useMemo( - () => packages.map((id) => normalizeSuiObjectId(id)), - [packages], - ); - - const supported = useMemo( - () => - data?.supported.filter((type) => normalizedPackages.includes(parseStructTag(type).address)), - [data, normalizedPackages], - ); - - const coinBalances = useMemo( - () => (rawCoinBalances ? filterTokenBalances(rawCoinBalances) : null), - [rawCoinBalances], - ); - - const validSwaps = useMemo( - () => - supported?.sort((a, b) => { - const suiType = normalizeStructTag(SUI_TYPE_ARG); - const balanceA = BigInt( - coinBalances?.find( - (balance) => normalizeStructTag(balance.coinType) === normalizeStructTag(a), - )?.totalBalance ?? 0, - ); - const balanceB = BigInt( - coinBalances?.find( - (balance) => normalizeStructTag(balance.coinType) === normalizeStructTag(b), - )?.totalBalance ?? 0, - ); - return a === suiType ? -1 : b === suiType ? 1 : Number(balanceB - balanceA); - }) ?? [], - [supported, coinBalances], - ); - - return { - isLoading: isSupportedCoinsLoading || isGetAllBalancesLoading, - data: validSwaps, - }; -} diff --git a/apps/wallet/src/ui/app/index.tsx b/apps/wallet/src/ui/app/index.tsx deleted file mode 100644 index 318ca3b529009..0000000000000 --- a/apps/wallet/src/ui/app/index.tsx +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useAppDispatch, useAppSelector } from '_hooks'; -import { UsdcPromo } from '_pages/home/usdc-promo/UsdcPromo'; -import { SwapPage } from '_pages/swap'; -import { CoinsSelectionPage } from '_pages/swap/CoinsSelectionPage'; -import { setNavVisibility } from '_redux/slices/app'; -import { isLedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount'; -import { persistableStorage } from '_src/shared/analytics/amplitude'; -import { type LedgerAccountsPublicKeys } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { toBase64 } from '@mysten/sui/utils'; -import { useEffect, useMemo } from 'react'; -import { Navigate, Outlet, Route, Routes, useLocation } from 'react-router-dom'; -import { throttle } from 'throttle-debounce'; - -import { useSuiLedgerClient } from './components/ledger/SuiLedgerClientProvider'; -import { useAccounts } from './hooks/useAccounts'; -import { useAutoLockMinutes } from './hooks/useAutoLockMinutes'; -import { useBackgroundClient } from './hooks/useBackgroundClient'; -import { useInitialPageView } from './hooks/useInitialPageView'; -import { useStorageMigrationStatus } from './hooks/useStorageMigrationStatus'; -import { AccountsPage } from './pages/accounts/AccountsPage'; -import { AddAccountPage } from './pages/accounts/AddAccountPage'; -import { BackupMnemonicPage } from './pages/accounts/BackupMnemonicPage'; -import { ExportAccountPage } from './pages/accounts/ExportAccountPage'; -import { ExportPassphrasePage } from './pages/accounts/ExportPassphrasePage'; -import { ForgotPasswordIndexPage } from './pages/accounts/forgot-password/ForgotPasswordIndexPage'; -import { ForgotPasswordPage } from './pages/accounts/forgot-password/ForgotPasswordPage'; -import { RecoverManyPage } from './pages/accounts/forgot-password/RecoverManyPage'; -import { RecoverPage } from './pages/accounts/forgot-password/RecoverPage'; -import { ResetPasswordPage } from './pages/accounts/forgot-password/ResetPasswordPage'; -import { ResetWarningPage } from './pages/accounts/forgot-password/ResetWarningPage'; -import { ImportLedgerAccountsPage } from './pages/accounts/ImportLedgerAccountsPage'; -import { ImportPassphrasePage } from './pages/accounts/ImportPassphrasePage'; -import { ImportPrivateKeyPage } from './pages/accounts/ImportPrivateKeyPage'; -import { ManageAccountsPage } from './pages/accounts/manage/ManageAccountsPage'; -import { ProtectAccountPage } from './pages/accounts/ProtectAccountPage'; -import { WelcomePage } from './pages/accounts/WelcomePage'; -import { ApprovalRequestPage } from './pages/approval-request'; -import HomePage, { - AppsPage, - AssetsPage, - CoinsSelectorPage, - KioskDetailsPage, - NFTDetailsPage, - NftTransferPage, - OnrampPage, - ReceiptPage, - TransactionBlocksPage, - TransferCoinPage, -} from './pages/home'; -import TokenDetailsPage from './pages/home/tokens/TokenDetailsPage'; -import { QredoConnectInfoPage } from './pages/qredo-connect/QredoConnectInfoPage'; -import { SelectQredoAccountsPage } from './pages/qredo-connect/SelectQredoAccountsPage'; -import { RestrictedPage } from './pages/restricted'; -import SiteConnectPage from './pages/site-connect'; -import { StorageMigrationPage } from './pages/StorageMigrationPage'; -import { AppType } from './redux/slices/app/AppType'; -import { PageMainLayout } from './shared/page-main-layout/PageMainLayout'; -import { Staking } from './staking/home'; - -const HIDDEN_MENU_PATHS = [ - '/nft-details', - '/nft-transfer', - '/receipt', - '/send', - '/send/select', - '/apps/disconnectapp', -]; - -const notifyUserActiveInterval = 5 * 1000; // 5 seconds - -const App = () => { - const dispatch = useAppDispatch(); - const isPopup = useAppSelector((state) => state.app.appType === AppType.popup); - useEffect(() => { - document.body.classList.remove('app-initializing'); - }, [isPopup]); - const location = useLocation(); - useEffect(() => { - const menuVisible = !HIDDEN_MENU_PATHS.some((aPath) => location.pathname.startsWith(aPath)); - dispatch(setNavVisibility(menuVisible)); - }, [location, dispatch]); - - useInitialPageView(); - const { data: accounts } = useAccounts(); - const allLedgerWithoutPublicKey = useMemo( - () => accounts?.filter(isLedgerAccountSerializedUI).filter(({ publicKey }) => !publicKey) || [], - [accounts], - ); - const backgroundClient = useBackgroundClient(); - const { connectToLedger, suiLedgerClient } = useSuiLedgerClient(); - useEffect(() => { - if (accounts?.length) { - // The user has accepted our terms of service after their primary - // account has been initialized (either by creating a new wallet - // or importing a previous account). This means we've gained - // consent and can persist device data to cookie storage - persistableStorage.persist(); - } - }, [accounts]); - useEffect(() => { - // update ledger accounts without the public key - (async () => { - if (allLedgerWithoutPublicKey.length) { - try { - if (!suiLedgerClient) { - await connectToLedger(); - return; - } - const publicKeysToStore: LedgerAccountsPublicKeys = []; - for (const { derivationPath, id } of allLedgerWithoutPublicKey) { - if (derivationPath) { - try { - const { publicKey } = await suiLedgerClient.getPublicKey(derivationPath); - publicKeysToStore.push({ - accountID: id, - publicKey: toBase64(publicKey), - }); - } catch (e) { - // do nothing - } - } - } - if (publicKeysToStore.length) { - await backgroundClient.storeLedgerAccountsPublicKeys({ publicKeysToStore }); - } - } catch (e) { - // do nothing - } - } - })(); - }, [allLedgerWithoutPublicKey, suiLedgerClient, backgroundClient, connectToLedger]); - const { data } = useAutoLockMinutes(); - const autoLockEnabled = !!data; - // use mouse move and key down events to detect user activity - // this is used to adjust the auto-lock timeout - useEffect(() => { - if (!autoLockEnabled) { - return; - } - const sendUpdateThrottled = throttle( - notifyUserActiveInterval, - () => { - backgroundClient.notifyUserActive(); - }, - { noTrailing: true }, - ); - document.addEventListener('mousemove', sendUpdateThrottled); - document.addEventListener('keydown', sendUpdateThrottled); - return () => { - document.removeEventListener('mousemove', sendUpdateThrottled); - document.removeEventListener('keydown', sendUpdateThrottled); - }; - }, [backgroundClient, autoLockEnabled]); - - const storageMigration = useStorageMigrationStatus(); - if (storageMigration.isPending || !storageMigration?.data) { - return null; - } - if (storageMigration.data !== 'ready') { - return ; - } - return ( - - } /> - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - - } - > - } /> - } /> - - } /> - } /> - }> - } /> - } /> - } /> - } /> - } /> - - - }> - } /> - } /> - - - ); -}; - -export default App; diff --git a/apps/wallet/src/ui/app/pages/StorageMigrationPage.tsx b/apps/wallet/src/ui/app/pages/StorageMigrationPage.tsx deleted file mode 100644 index eb4d5ca0aadcc..0000000000000 --- a/apps/wallet/src/ui/app/pages/StorageMigrationPage.tsx +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useMutation } from '@tanstack/react-query'; -import { toast } from 'react-hot-toast'; - -import LoadingIndicator from '../components/loading/LoadingIndicator'; -import { PasswordInputDialog } from '../components/PasswordInputDialog'; -import { useBackgroundClient } from '../hooks/useBackgroundClient'; -import { useStorageMigrationStatus } from '../hooks/useStorageMigrationStatus'; -import { CardLayout } from '../shared/card-layout'; -import { Toaster } from '../shared/toaster'; - -export function StorageMigrationPage() { - const { data } = useStorageMigrationStatus(); - const backgroundClient = useBackgroundClient(); - const migrationMutation = useMutation({ - mutationKey: ['do storage migration'], - mutationFn: ({ password }: { password: string }) => - backgroundClient.doStorageMigration({ password }), - onSuccess: () => { - toast.success('Storage migration done'); - }, - }); - if (!data || data === 'ready') { - return null; - } - return ( - <> - - {data === 'required' && !migrationMutation.isSuccess ? ( - { - await migrationMutation.mutateAsync({ password }); - }} - title="Please insert your wallet password" - legacyAccounts - /> - ) : ( -
    - -
    - )} -
    - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/AccountsPage.tsx b/apps/wallet/src/ui/app/pages/accounts/AccountsPage.tsx deleted file mode 100644 index 5a019944cb5cc..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/AccountsPage.tsx +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Outlet } from 'react-router-dom'; - -import { Toaster } from '../../shared/toaster'; - -export function AccountsPage() { - return ( - <> - - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx b/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx deleted file mode 100644 index 50440f0240270..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { Text } from '_app/shared/text'; -import Overlay from '_components/overlay'; -import { - zkLoginProviderDataMap, - type ZkLoginProvider, -} from '_src/background/accounts/zklogin/providers'; -import { ampli } from '_src/shared/analytics/ampli'; -import { LedgerLogo17 as LedgerLogo } from '@mysten/icons'; -import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react'; -import toast from 'react-hot-toast'; -import { useNavigate, useSearchParams } from 'react-router-dom'; -import Browser from 'webextension-polyfill'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { ZkLoginButtons } from '../../components/accounts/ZkLoginButtons'; -import { ConnectLedgerModal } from '../../components/ledger/ConnectLedgerModal'; -import { getLedgerConnectionErrorMessage } from '../../helpers/errorMessages'; -import { useAppSelector } from '../../hooks'; -import { useCountAccountsByType } from '../../hooks/useCountAccountByType'; -import { useCreateAccountsMutation } from '../../hooks/useCreateAccountMutation'; -import { AppType } from '../../redux/slices/app/AppType'; - -async function openTabWithSearchParam(searchParam: string, searchParamValue: string) { - const currentURL = new URL(window.location.href); - const [currentHash, currentHashSearch] = currentURL.hash.split('?'); - const urlSearchParams = new URLSearchParams(currentHashSearch); - urlSearchParams.set(searchParam, searchParamValue); - currentURL.hash = `${currentHash}?${urlSearchParams.toString()}`; - currentURL.searchParams.delete('type'); - await Browser.tabs.create({ - url: currentURL.href, - }); -} - -export function AddAccountPage() { - const [searchParams, setSearchParams] = useSearchParams(); - const navigate = useNavigate(); - const sourceFlow = searchParams.get('sourceFlow') || 'Unknown'; - const showSocialSignInOptions = sourceFlow !== 'Onboarding'; - const forceShowLedger = - searchParams.has('showLedger') && searchParams.get('showLedger') !== 'false'; - const [, setAccountsFormValues] = useAccountsFormContext(); - const isPopup = useAppSelector((state) => state.app.appType === AppType.popup); - const [isConnectLedgerModalOpen, setConnectLedgerModalOpen] = useState(forceShowLedger); - const createAccountsMutation = useCreateAccountsMutation(); - const createZkLoginAccount = useCallback( - async (provider: ZkLoginProvider) => { - await setAccountsFormValues({ type: 'zkLogin', provider }); - await createAccountsMutation.mutateAsync( - { - type: 'zkLogin', - }, - { - onSuccess: () => { - navigate('/tokens'); - }, - onError: (error) => { - toast.error((error as Error)?.message || 'Failed to create account. (Unknown error)'); - }, - }, - ); - }, - [setAccountsFormValues, createAccountsMutation, navigate], - ); - const [forcedZkLoginProvider, setForcedZkLoginProvider] = useState(null); - const forceZkLoginWithProviderRef = useRef(searchParams.get('forceZkLoginProvider')); - const forcedLoginHandledRef = useRef(false); - const { data: accountsTotalByType, isPending: isAccountsCountLoading } = useCountAccountsByType(); - useEffect(() => { - if (isAccountsCountLoading) { - return; - } - const zkLoginProvider = forceZkLoginWithProviderRef.current as ZkLoginProvider; - if ( - zkLoginProvider && - zkLoginProviderDataMap[zkLoginProvider] && - !forcedLoginHandledRef.current - ) { - const totalProviderAccounts = accountsTotalByType?.zkLogin?.extra?.[zkLoginProvider] || 0; - if (totalProviderAccounts === 0) { - setForcedZkLoginProvider(zkLoginProvider); - createZkLoginAccount(zkLoginProvider).finally(() => setForcedZkLoginProvider(null)); - } - const newURLSearchParams = new URLSearchParams(searchParams.toString()); - newURLSearchParams.delete('forceZkLoginProvider'); - setSearchParams(newURLSearchParams.toString()); - forcedLoginHandledRef.current = true; - } - }, [ - setSearchParams, - accountsTotalByType, - searchParams, - createZkLoginAccount, - isAccountsCountLoading, - ]); - return ( - navigate('/')}> -
    -
    - {showSocialSignInOptions && ( - { - if (isPopup) { - await openTabWithSearchParam('forceZkLoginProvider', provider); - window.close(); - return; - } else { - return createZkLoginAccount(provider); - } - }} - /> - )} -
    -
    -
    -
    -
    -
    - {isConnectLedgerModalOpen && ( - { - setConnectLedgerModalOpen(false); - }} - onError={(error) => { - setConnectLedgerModalOpen(false); - toast.error(getLedgerConnectionErrorMessage(error) || 'Something went wrong.'); - }} - onConfirm={() => { - ampli.connectedHardwareWallet({ hardwareWalletType: 'Ledger' }); - navigate('/accounts/import-ledger-accounts'); - }} - /> - )} -
    - ); -} - -type SectionProps = { - title: string; - children: ReactNode; -}; - -function Section({ title, children }: SectionProps) { - return ( -
    -
    -
    - - {title} - -
    -
    - {children} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/BackupMnemonicPage.tsx b/apps/wallet/src/ui/app/pages/accounts/BackupMnemonicPage.tsx deleted file mode 100644 index d51db00537ab8..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/BackupMnemonicPage.tsx +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { CardLayout } from '_app/shared/card-layout'; -import { Text } from '_app/shared/text'; -import Alert from '_components/alert'; -import Loading from '_components/loading'; -import { HideShowDisplayBox } from '_src/ui/app/components/HideShowDisplayBox'; -import { ArrowLeft16, Check12 } from '@mysten/icons'; -import { useEffect, useMemo, useState } from 'react'; -import { Navigate, useLocation, useNavigate, useParams } from 'react-router-dom'; - -import { VerifyPasswordModal } from '../../components/accounts/VerifyPasswordModal'; -import { useAccountSources } from '../../hooks/useAccountSources'; -import { useExportPassphraseMutation } from '../../hooks/useExportPassphraseMutation'; - -export function BackupMnemonicPage() { - const [passwordCopied, setPasswordCopied] = useState(false); - const { state } = useLocation(); - const { accountSourceID } = useParams(); - const { data: accountSources, isPending } = useAccountSources(); - const selectedSource = useMemo( - () => accountSources?.find(({ id }) => accountSourceID === id), - [accountSources, accountSourceID], - ); - const isOnboardingFlow = !!state?.onboarding; - const [showPasswordDialog, setShowPasswordDialog] = useState(false); - const [passwordConfirmed, setPasswordConfirmed] = useState(false); - const requirePassword = !isOnboardingFlow || !!selectedSource?.isLocked; - const passphraseMutation = useExportPassphraseMutation(); - useEffect(() => { - (async () => { - if ( - (requirePassword && !passwordConfirmed) || - !passphraseMutation.isIdle || - !accountSourceID - ) { - return; - } - passphraseMutation.mutate({ accountSourceID: accountSourceID }); - })(); - }, [requirePassword, passwordConfirmed, accountSourceID, passphraseMutation]); - useEffect(() => { - if (requirePassword && !passwordConfirmed && !showPasswordDialog) { - setShowPasswordDialog(true); - } - }, [requirePassword, passwordConfirmed, showPasswordDialog]); - const navigate = useNavigate(); - if (!isPending && selectedSource?.type !== 'mnemonic') { - return ; - } - return ( - - {showPasswordDialog ? ( - - { - navigate(-1); - }} - onVerify={async (password) => { - await passphraseMutation.mutateAsync({ - password, - accountSourceID: selectedSource!.id, - }); - setPasswordConfirmed(true); - setShowPasswordDialog(false); - }} - /> - - ) : ( - -
    -
    -
    - - Recovery phrase - -
    -
    - - Your recovery phrase makes it easy to back up and restore your account. - -
    - - {passphraseMutation.data ? ( - - ) : ( - - {(passphraseMutation.error as Error)?.message || 'Something went wrong'} - - )} - -
    - - Warning - -
    -
    - - Never disclose your secret recovery phrase. Anyone can take over your account with - it. - -
    -
    - {isOnboardingFlow ? ( -
    - -
    - ) : null} -
    -
    - - )} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ExportAccountPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ExportAccountPage.tsx deleted file mode 100644 index 0cbc754f8219b..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ExportAccountPage.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useBackgroundClient } from '_src/ui/app/hooks/useBackgroundClient'; -import { useMutation } from '@tanstack/react-query'; -import { Navigate, useNavigate, useParams } from 'react-router-dom'; - -import { VerifyPasswordModal } from '../../components/accounts/VerifyPasswordModal'; -import Alert from '../../components/alert'; -import { HideShowDisplayBox } from '../../components/HideShowDisplayBox'; -import Loading from '../../components/loading'; -import Overlay from '../../components/overlay'; -import { useAccounts } from '../../hooks/useAccounts'; - -export function ExportAccountPage() { - const { accountID } = useParams(); - const { data: allAccounts, isPending } = useAccounts(); - const account = allAccounts?.find(({ id }) => accountID === id) || null; - const backgroundClient = useBackgroundClient(); - const exportMutation = useMutation({ - mutationKey: ['export-account', accountID], - mutationFn: async (password: string) => { - if (!account) { - return null; - } - return ( - await backgroundClient.exportAccountKeyPair({ - password, - accountID: account.id, - }) - ).keyPair; - }, - }); - const navigate = useNavigate(); - if (!account && !isPending) { - return ; - } - return ( - navigate(-1)} showModal> - - {exportMutation.data ? ( -
    - -
    Do not share your Private Key!
    -
    It provides full control of your account.
    -
    - -
    - ) : ( - { - await exportMutation.mutateAsync(password); - }} - onClose={() => navigate(-1)} - /> - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ExportPassphrasePage.tsx b/apps/wallet/src/ui/app/pages/accounts/ExportPassphrasePage.tsx deleted file mode 100644 index 4c7766e8aec4c..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ExportPassphrasePage.tsx +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Alert from '_components/alert'; -import { HideShowDisplayBox } from '_components/HideShowDisplayBox'; -import { Navigate, useNavigate, useParams } from 'react-router-dom'; - -import { VerifyPasswordModal } from '../../components/accounts/VerifyPasswordModal'; -import Loading from '../../components/loading'; -import Overlay from '../../components/overlay'; -import { useAccountSources } from '../../hooks/useAccountSources'; -import { useExportPassphraseMutation } from '../../hooks/useExportPassphraseMutation'; - -export function ExportPassphrasePage() { - const { accountSourceID } = useParams(); - const { data: allAccountSources, isPending } = useAccountSources(); - const accountSource = allAccountSources?.find(({ id }) => id === accountSourceID) || null; - const navigate = useNavigate(); - const exportMutation = useExportPassphraseMutation(); - if (!isPending && accountSource?.type !== 'mnemonic') { - return ; - } - return ( - navigate(-1)} showModal> - - {exportMutation.data ? ( -
    - -
    Do not share your Passphrase!
    -
    - It provides full control of all accounts derived from it. -
    -
    - -
    - ) : ( - { - await exportMutation.mutateAsync({ password, accountSourceID: accountSource!.id }); - }} - onClose={() => navigate(-1)} - /> - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx deleted file mode 100644 index 10cffcb803f20..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { Link } from '_src/ui/app/shared/Link'; -import { Text } from '_src/ui/app/shared/text'; -import { - Spinner16 as SpinnerIcon, - ThumbUpStroke32 as ThumbUpIcon, - LockUnlocked16 as UnlockedLockIcon, -} from '@mysten/icons'; -import { useCallback, useEffect, useState } from 'react'; -import toast from 'react-hot-toast'; -import { useNavigate, useSearchParams } from 'react-router-dom'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { - LedgerAccountList, - type SelectableLedgerAccount, -} from '../../components/ledger/LedgerAccountList'; -import { - useDeriveLedgerAccounts, - type DerivedLedgerAccount, -} from '../../components/ledger/useDeriveLedgerAccounts'; -import Overlay from '../../components/overlay'; -import { getSuiApplicationErrorMessage } from '../../helpers/errorMessages'; -import { useAccounts } from '../../hooks/useAccounts'; - -const numLedgerAccountsToDeriveByDefault = 10; - -export function ImportLedgerAccountsPage() { - const [searchParams] = useSearchParams(); - const successRedirect = searchParams.get('successRedirect') || '/tokens'; - const navigate = useNavigate(); - const { data: existingAccounts } = useAccounts(); - const [selectedLedgerAccounts, setSelectedLedgerAccounts] = useState([]); - const { - data: ledgerAccounts, - error: ledgerError, - isPending: areLedgerAccountsLoading, - isError: encounteredDerviceAccountsError, - } = useDeriveLedgerAccounts({ - numAccountsToDerive: numLedgerAccountsToDeriveByDefault, - select: (ledgerAccounts) => { - return ledgerAccounts.filter( - ({ address }) => !existingAccounts?.some((account) => account.address === address), - ); - }, - }); - - useEffect(() => { - if (ledgerError) { - toast.error(getSuiApplicationErrorMessage(ledgerError) || 'Something went wrong.'); - navigate(-1); - } - }, [ledgerError, navigate]); - - const onAccountClick = useCallback( - (targetAccount: SelectableLedgerAccount) => { - if (targetAccount.isSelected) { - setSelectedLedgerAccounts((prevState) => - prevState.filter((ledgerAccount) => { - return ledgerAccount.address !== targetAccount.address; - }), - ); - } else { - setSelectedLedgerAccounts((prevState) => [...prevState, targetAccount]); - } - }, - [setSelectedLedgerAccounts], - ); - const numImportableAccounts = ledgerAccounts?.length; - const numSelectedAccounts = selectedLedgerAccounts.length; - const areAllAccountsImported = numImportableAccounts === 0; - const areAllAccountsSelected = numSelectedAccounts === numImportableAccounts; - const isUnlockButtonDisabled = numSelectedAccounts === 0; - const isSelectAllButtonDisabled = areAllAccountsImported || areAllAccountsSelected; - const [, setAccountsFormValues] = useAccountsFormContext(); - - let summaryCardBody: JSX.Element | null = null; - if (areLedgerAccountsLoading) { - summaryCardBody = ( -
    - - - Looking for accounts - -
    - ); - } else if (areAllAccountsImported) { - summaryCardBody = ( -
    - - - All Ledger accounts have been imported. - -
    - ); - } else if (!encounteredDerviceAccountsError) { - const selectedLedgerAddresses = selectedLedgerAccounts.map(({ address }) => address); - summaryCardBody = ( -
    - ({ - ...ledgerAccount, - isSelected: selectedLedgerAddresses.includes(ledgerAccount.address), - }))} - onAccountClick={onAccountClick} - /> -
    - ); - } - - return ( - { - navigate(-1); - }} - > -
    -
    -
    - - {areAllAccountsImported ? 'Ledger Accounts ' : 'Connect Ledger Accounts'} - -
    -
    {summaryCardBody}
    -
    -
    - { - if (ledgerAccounts) { - setSelectedLedgerAccounts(ledgerAccounts); - } - }} - disabled={isSelectAllButtonDisabled} - /> -
    -
    -
    -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx deleted file mode 100644 index dfe92b812f6f2..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { entropyToSerialized, mnemonicToEntropy } from '_src/shared/utils/bip39'; -import { useNavigate } from 'react-router-dom'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { ImportRecoveryPhraseForm } from '../../components/accounts/ImportRecoveryPhraseForm'; -import { Heading } from '../../shared/heading'; - -export function ImportPassphrasePage() { - const navigate = useNavigate(); - const [, setFormValues] = useAccountsFormContext(); - return ( -
    - - Wallet Setup - -
    - - Add Existing Account - -
    -
    -
    - - Enter your 12-word Recovery Phrase - -
    - { - setFormValues({ - type: 'import-mnemonic', - entropy: entropyToSerialized(mnemonicToEntropy(recoveryPhrase.join(' '))), - }); - navigate('/accounts/protect-account?accountType=import-mnemonic'); - }} - /> -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx deleted file mode 100644 index e8c46a7ac59b1..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { useNavigate } from 'react-router-dom'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { ImportPrivateKeyForm } from '../../components/accounts/ImportPrivateKeyForm'; -import { Heading } from '../../shared/heading'; - -export function ImportPrivateKeyPage() { - const navigate = useNavigate(); - const [, setAccountsFormValues] = useAccountsFormContext(); - - return ( -
    - - Wallet Setup - -
    - - Import Private Key - -
    -
    - { - setAccountsFormValues({ - type: 'imported', - keyPair: privateKey, - }); - navigate('/accounts/protect-account?accountType=imported'); - }} - /> -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx deleted file mode 100644 index 0b3f762a7657b..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { isMnemonicSerializedUiAccount } from '_src/background/accounts/MnemonicAccount'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { toast } from 'react-hot-toast'; -import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; - -import { ProtectAccountForm } from '../../components/accounts/ProtectAccountForm'; -import { VerifyPasswordModal } from '../../components/accounts/VerifyPasswordModal'; -import Loading from '../../components/loading'; -import { useAccounts } from '../../hooks/useAccounts'; -import { autoLockDataToMinutes } from '../../hooks/useAutoLockMinutes'; -import { useAutoLockMinutesMutation } from '../../hooks/useAutoLockMinutesMutation'; -import { useCreateAccountsMutation, type CreateType } from '../../hooks/useCreateAccountMutation'; -import { Heading } from '../../shared/heading'; - -const allowedAccountTypes: CreateType[] = [ - 'new-mnemonic', - 'import-mnemonic', - 'mnemonic-derived', - 'imported', - 'ledger', - 'qredo', -]; - -type AllowedAccountTypes = (typeof allowedAccountTypes)[number]; - -function isAllowedAccountType(accountType: string): accountType is AllowedAccountTypes { - return allowedAccountTypes.includes(accountType as any); -} - -export function ProtectAccountPage() { - const [searchParams] = useSearchParams(); - const accountType = searchParams.get('accountType') || ''; - const successRedirect = searchParams.get('successRedirect') || '/tokens'; - const navigate = useNavigate(); - const { data: accounts } = useAccounts(); - const createMutation = useCreateAccountsMutation(); - const hasPasswordAccounts = useMemo( - () => accounts && accounts.some(({ isPasswordUnlockable }) => isPasswordUnlockable), - [accounts], - ); - const [showVerifyPasswordView, setShowVerifyPasswordView] = useState(null); - useEffect(() => { - if ( - typeof hasPasswordAccounts !== 'undefined' && - !(createMutation.isSuccess || createMutation.isPending) - ) { - setShowVerifyPasswordView(hasPasswordAccounts); - } - }, [hasPasswordAccounts, createMutation.isSuccess, createMutation.isPending]); - const createAccountCallback = useCallback( - async (password: string, type: CreateType) => { - try { - const createdAccounts = await createMutation.mutateAsync({ - type, - password, - }); - if (type === 'new-mnemonic' && isMnemonicSerializedUiAccount(createdAccounts[0])) { - navigate(`/accounts/backup/${createdAccounts[0].sourceID}`, { - replace: true, - state: { - onboarding: true, - }, - }); - } else { - navigate(successRedirect, { replace: true }); - } - } catch (e) { - toast.error((e as Error).message ?? 'Failed to create account'); - } - }, - [createMutation, navigate, successRedirect], - ); - const autoLockMutation = useAutoLockMinutesMutation(); - if (!isAllowedAccountType(accountType)) { - return ; - } - - return ( -
    - - {showVerifyPasswordView ? ( - navigate(-1)} - onVerify={(password) => createAccountCallback(password, accountType)} - /> - ) : ( - <> - - Wallet Setup - -
    - - Protect Account with a Password Lock - -
    -
    - { - await autoLockMutation.mutateAsync({ minutes: autoLockDataToMinutes(autoLock) }); - await createAccountCallback(password.input, accountType); - }} - /> -
    - - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/WelcomePage.tsx b/apps/wallet/src/ui/app/pages/accounts/WelcomePage.tsx deleted file mode 100644 index 94775feeeca62..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/WelcomePage.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { Heading } from '_app/shared/heading'; -import { Text } from '_app/shared/text'; -import Loading from '_components/loading'; -import Logo from '_components/logo'; -import { useFullscreenGuard, useInitializedGuard } from '_hooks'; -import WelcomeSplash from '_src/ui/assets/images/WelcomeSplash.svg'; -import { toast } from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { ZkLoginButtons } from '../../components/accounts/ZkLoginButtons'; -import { useCreateAccountsMutation } from '../../hooks/useCreateAccountMutation'; - -export function WelcomePage() { - const createAccountsMutation = useCreateAccountsMutation(); - const isFullscreenGuardLoading = useFullscreenGuard(true); - const isInitializedLoading = useInitializedGuard( - false, - !(createAccountsMutation.isPending || createAccountsMutation.isSuccess), - ); - const [, setAccountsFormValues] = useAccountsFormContext(); - const navigate = useNavigate(); - return ( - -
    -
    - -
    -
    - - Welcome to Sui Wallet - -
    - - Connecting you to the decentralized web and Sui network. - -
    -
    -
    - -
    -
    - - Sign in with your preferred service - - { - setAccountsFormValues({ type: 'zkLogin', provider }); - await createAccountsMutation.mutateAsync( - { - type: 'zkLogin', - }, - { - onSuccess: () => { - navigate('/tokens'); - }, - onError: (error) => { - toast.error( - (error as Error)?.message || 'Failed to create account. (Unknown error)', - ); - }, - }, - ); - }} - /> -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordIndexPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordIndexPage.tsx deleted file mode 100644 index 04fff295519d1..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordIndexPage.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { useAccountSources } from '../../../hooks/useAccountSources'; - -export function ForgotPasswordIndexPage() { - const allAccountSources = useAccountSources(); - const navigate = useNavigate(); - const totalRecoverable = - allAccountSources.data?.filter(({ type }) => type === 'mnemonic').length || 0; - useEffect(() => { - if (allAccountSources.isPending) { - return; - } - const url = - totalRecoverable === 0 ? '/' : totalRecoverable === 1 ? './recover' : './recover-many'; - navigate(url, { replace: true }); - }, [allAccountSources.isPending, totalRecoverable, navigate]); - return null; -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordPage.tsx deleted file mode 100644 index 44a0f0ce91581..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ForgotPasswordPage.tsx +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type PasswordRecoveryData } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { createContext, useCallback, useContext, useState } from 'react'; -import { Outlet } from 'react-router-dom'; - -const forgotPasswordContext = createContext<{ - value: PasswordRecoveryData[]; - add: (data: PasswordRecoveryData) => void; - clear: () => void; -} | null>(null); - -export function useForgotPasswordContext() { - const context = useContext(forgotPasswordContext); - if (!context) { - throw new Error('Missing forgot password context'); - } - return context; -} - -export function ForgotPasswordPage() { - const [recoveryData, setRecoveryData] = useState([]); - const add = useCallback((data: PasswordRecoveryData) => { - setRecoveryData((existing) => [ - ...existing.filter(({ accountSourceID }) => accountSourceID !== data.accountSourceID), - data, - ]); - }, []); - const clear = useCallback(() => { - setRecoveryData([]); - }, []); - return ( -
    - - - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverManyPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverManyPage.tsx deleted file mode 100644 index f469f18b00251..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverManyPage.tsx +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { entropyToSerialized, mnemonicToEntropy } from '_src/shared/utils/bip39'; -import { ImportRecoveryPhraseForm } from '_src/ui/app/components/accounts/ImportRecoveryPhraseForm'; -import Overlay from '_src/ui/app/components/overlay'; -import { useRecoveryDataMutation } from '_src/ui/app/hooks/useRecoveryDataMutation'; -import { useEffect, useState } from 'react'; -import toast from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; - -import { RecoverAccountsGroup } from '../../../components/accounts/RecoverAccountsGroup'; -import { useAccountGroups } from '../../../hooks/useAccountGroups'; -import { useAccountSources } from '../../../hooks/useAccountSources'; -import { Button } from '../../../shared/ButtonUI'; -import { Heading } from '../../../shared/heading'; -import { Text } from '../../../shared/text'; -import { useForgotPasswordContext } from './ForgotPasswordPage'; - -export function RecoverManyPage() { - const allAccountSources = useAccountSources(); - const accountGroups = useAccountGroups(); - const navigate = useNavigate(); - useEffect(() => { - if ( - !allAccountSources.isPending && - !allAccountSources.data?.find(({ type }) => type === 'mnemonic') - ) { - navigate('/', { replace: true }); - } - }, [allAccountSources.isPending, allAccountSources.data, navigate]); - const { value } = useForgotPasswordContext(); - const addRecoveryDataMutation = useRecoveryDataMutation(); - const [recoverInfo, setRecoverInfo] = useState<{ title: string; accountSourceID: string } | null>( - null, - ); - return ( - <> -
    -
    - - Forgot Password? - - - Please complete the recovery process for the accounts below - -
    -
    - {Object.entries(accountGroups['mnemonic-derived']).map(([sourceID, accounts], index) => { - const recoveryData = value.find(({ accountSourceID }) => accountSourceID === sourceID); - const title = `Passphrase ${index + 1}`; - return ( - { - setRecoverInfo({ title, accountSourceID: sourceID }); - }} - recoverDone={!!recoveryData} - /> - ); - })} -
    -
    -
    -
    - { - if (addRecoveryDataMutation.isPending) { - return; - } - setRecoverInfo(null); - }} - background="bg-sui-lightest" - > -
    - - Enter your 12-word Recovery Phrase - - { - if (!recoverInfo) { - return; - } - try { - await addRecoveryDataMutation.mutateAsync({ - type: 'mnemonic', - entropy: entropyToSerialized(mnemonicToEntropy(recoveryPhrase.join(' '))), - accountSourceID: recoverInfo.accountSourceID, - }); - setRecoverInfo(null); - } catch (e) { - toast.error((e as Error)?.message || 'Something went wrong'); - } - }} - /> -
    -
    - - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverPage.tsx deleted file mode 100644 index 5e0b94dee5085..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/RecoverPage.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { entropyToSerialized, mnemonicToEntropy } from '_src/shared/utils/bip39'; -import { ImportRecoveryPhraseForm } from '_src/ui/app/components/accounts/ImportRecoveryPhraseForm'; -import { useRecoveryDataMutation } from '_src/ui/app/hooks/useRecoveryDataMutation'; -import { useEffect } from 'react'; -import toast from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; - -import { useAccountSources } from '../../../hooks/useAccountSources'; -import { Heading } from '../../../shared/heading'; -import { Text } from '../../../shared/text'; - -export function RecoverPage() { - const allAccountSources = useAccountSources(); - const navigate = useNavigate(); - const mnemonicAccountSource = allAccountSources.data?.find(({ type }) => type === 'mnemonic'); - useEffect(() => { - if (!allAccountSources.isPending && !mnemonicAccountSource) { - navigate('/', { replace: true }); - } - }, [allAccountSources.isPending, mnemonicAccountSource, navigate]); - const recoveryDataMutation = useRecoveryDataMutation(); - if (!mnemonicAccountSource) { - return null; - } - return ( -
    -
    - - Forgot Password? - - - Enter your 12-word Recovery Phrase - -
    -
    - { - try { - await recoveryDataMutation.mutateAsync({ - type: 'mnemonic', - accountSourceID: mnemonicAccountSource.id, - entropy: entropyToSerialized(mnemonicToEntropy(recoveryPhrase.join(' '))), - }); - navigate('../warning'); - } catch (e) { - toast.error((e as Error)?.message || 'Something went wrong'); - } - }} - /> -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetPasswordPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetPasswordPage.tsx deleted file mode 100644 index 3a91bff2e0899..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetPasswordPage.tsx +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useAutoLockMinutesMutation } from '_src/ui/app/hooks/useAutoLockMinutesMutation'; -import { useResetPasswordMutation } from '_src/ui/app/hooks/useResetPasswordMutation'; -import { toast } from 'react-hot-toast'; -import { Navigate, useNavigate } from 'react-router-dom'; - -import { ProtectAccountForm } from '../../../components/accounts/ProtectAccountForm'; -import { autoLockDataToMinutes } from '../../../hooks/useAutoLockMinutes'; -import { Heading } from '../../../shared/heading'; -import { useForgotPasswordContext } from './ForgotPasswordPage'; - -export function ResetPasswordPage() { - const { value, clear } = useForgotPasswordContext(); - const autoLockMutation = useAutoLockMinutesMutation(); - const resetPasswordMutation = useResetPasswordMutation(); - const navigate = useNavigate(); - if (!value.length && !resetPasswordMutation.isSuccess) { - return ; - } - return ( -
    -
    - - Protect Account with a Password Lock - -
    -
    - { - try { - await autoLockMutation.mutateAsync({ minutes: autoLockDataToMinutes(autoLock) }); - await resetPasswordMutation.mutateAsync({ - password: password.input, - recoveryData: value, - }); - clear(); - toast.success('Password reset'); - navigate('/'); - } catch (e) { - toast.error((e as Error)?.message || 'Something went wrong'); - } - }} - displayToS - /> -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetWarningPage.tsx b/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetWarningPage.tsx deleted file mode 100644 index d582dda9d8fa9..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/forgot-password/ResetWarningPage.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Button } from '_app/shared/ButtonUI'; -import { type AccountType } from '_src/background/accounts/Account'; -import { useAccounts } from '_src/ui/app/hooks/useAccounts'; -import { Navigate, useNavigate } from 'react-router-dom'; - -import { RecoverAccountsGroup } from '../../../components/accounts/RecoverAccountsGroup'; -import { useAccountGroups } from '../../../hooks/useAccountGroups'; -import { Heading } from '../../../shared/heading'; -import { Text } from '../../../shared/text'; -import { getGroupTitle } from '../manage/AccountGroup'; -import { useForgotPasswordContext } from './ForgotPasswordPage'; - -const zkLoginType: AccountType = 'zkLogin'; - -export function ResetWarningPage() { - const navigate = useNavigate(); - const accountGroups = useAccountGroups(); - const { value } = useForgotPasswordContext(); - const accountGroupsToRemove = Object.entries(accountGroups).flatMap(([groupType, aGroup]) => - Object.entries(aGroup).filter( - ([sourceID]) => - groupType !== zkLoginType && - !value.find(({ accountSourceID }) => accountSourceID === sourceID), - ), - ); - const { isPending } = useAccounts(); - if (!value.length) { - return ; - } - if (!accountGroupsToRemove.length && !isPending) { - return ; - } - return ( -
    -
    - - Reset Password - - - To ensure wallet security, the following accounts will be removed as part of the password - reset process. You will need to connect/import them again. - -
    -
    - {accountGroupsToRemove.map(([sourceID, accounts]) => ( - - ))} -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx b/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx deleted file mode 100644 index c788e69745594..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { type AccountType, type SerializedUIAccount } from '_src/background/accounts/Account'; -import { type ZkLoginProvider } from '_src/background/accounts/zklogin/providers'; -import { isZkLoginAccountSerializedUI } from '_src/background/accounts/zklogin/ZkLoginAccount'; -import { AccountIcon } from '_src/ui/app/components/accounts/AccountIcon'; -import { AccountItem } from '_src/ui/app/components/accounts/AccountItem'; -import { useAccountsFormContext } from '_src/ui/app/components/accounts/AccountsFormContext'; -import { NicknameDialog } from '_src/ui/app/components/accounts/NicknameDialog'; -import { VerifyPasswordModal } from '_src/ui/app/components/accounts/VerifyPasswordModal'; -import { useAccounts } from '_src/ui/app/hooks/useAccounts'; -import { useAccountSources } from '_src/ui/app/hooks/useAccountSources'; -import { useBackgroundClient } from '_src/ui/app/hooks/useBackgroundClient'; -import { useCreateAccountsMutation } from '_src/ui/app/hooks/useCreateAccountMutation'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '_src/ui/app/shared/Dialog'; -import { Heading } from '_src/ui/app/shared/heading'; -import { Text } from '_src/ui/app/shared/text'; -import { ButtonOrLink, type ButtonOrLinkProps } from '_src/ui/app/shared/utils/ButtonOrLink'; -import { ArrowBgFill16, Plus12 } from '@mysten/icons'; -import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; -import { useMutation } from '@tanstack/react-query'; -import { forwardRef, useState } from 'react'; -import toast from 'react-hot-toast'; - -const accountTypeToLabel: Record = { - 'mnemonic-derived': 'Passphrase Derived', - qredo: 'Qredo', - imported: 'Imported', - ledger: 'Ledger', - zkLogin: 'zkLogin', -}; - -const providerToLabel: Record = { - google: 'Google', - twitch: 'Twitch', - facebook: 'Facebook', - kakao: 'Kakao', -}; - -export function getGroupTitle(aGroupAccount: SerializedUIAccount) { - // TODO: revisit this logic for determining account provider - return isZkLoginAccountSerializedUI(aGroupAccount) - ? providerToLabel[aGroupAccount?.provider] ?? 'zkLogin' - : accountTypeToLabel[aGroupAccount?.type] || ''; -} - -// todo: we probably have some duplication here with the various FooterLink / ButtonOrLink -// components - we should look to add these to base components somewhere -const FooterLink = forwardRef( - ({ children, to, ...props }, ref) => { - return ( - - - {children} - - - ); - }, -); - -// todo: this is slightly different than the account footer in the AccountsList - look to consolidate :( -function AccountFooter({ accountID, showExport }: { accountID: string; showExport?: boolean }) { - const allAccounts = useAccounts(); - const totalAccounts = allAccounts?.data?.length || 0; - const backgroundClient = useBackgroundClient(); - const [isConfirmationVisible, setIsConfirmationVisible] = useState(false); - const removeAccountMutation = useMutation({ - mutationKey: ['remove account mutation', accountID], - mutationFn: async () => { - await backgroundClient.removeAccount({ accountID }); - setIsConfirmationVisible(false); - }, - }); - return ( - <> -
    -
    - Edit Nickname} /> - {showExport ? ( - Export Private Key - ) : null} - {allAccounts.isPending ? null : ( - setIsConfirmationVisible(true)} - disabled={isConfirmationVisible} - > - Remove - - )} -
    -
    - - e.preventDefault()}> - - Are you sure you want to remove this account? - - {totalAccounts === 1 ? ( -
    - - Removing this account will require you to set up your Sui wallet again. - -
    - ) : null} - -
    -
    -
    -
    -
    - - ); -} - -export function AccountGroup({ - accounts, - type, - accountSourceID, -}: { - accounts: SerializedUIAccount[]; - type: AccountType; - accountSourceID?: string; -}) { - const createAccountMutation = useCreateAccountsMutation(); - const isMnemonicDerivedGroup = type === 'mnemonic-derived'; - const [accountsFormValues, setAccountsFormValues] = useAccountsFormContext(); - const [isPasswordModalVisible, setPasswordModalVisible] = useState(false); - const { data: accountSources } = useAccountSources(); - const accountSource = accountSources?.find(({ id }) => id === accountSourceID); - return ( - <> - -
    - -
    - - - {getGroupTitle(accounts[0])} - -
    - {isMnemonicDerivedGroup && accountSource ? ( - { - // prevent the collapsible from closing when clicking the "new" button - e.stopPropagation(); - setAccountsFormValues({ - type: 'mnemonic-derived', - sourceID: accountSource.id, - }); - if (accountSource.isLocked) { - setPasswordModalVisible(true); - } else { - createAccountMutation.mutate({ type: 'mnemonic-derived' }); - } - }} - className="items-center justify-center gap-0.5 cursor-pointer appearance-none uppercase flex bg-transparent border-0 outline-none text-hero hover:text-hero-darkest" - > - - - New - - - ) : null} -
    - - -
    - {accounts.map((account) => { - return ( - } - footer={ - - } - /> - ); - })} - {isMnemonicDerivedGroup && accountSource ? ( -
    -
    -
    - - {isPasswordModalVisible ? ( - { - if (accountsFormValues.current && accountsFormValues.current.type !== 'zkLogin') { - await createAccountMutation.mutateAsync({ - type: accountsFormValues.current.type, - password, - }); - } - setPasswordModalVisible(false); - }} - onClose={() => setPasswordModalVisible(false)} - /> - ) : null} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/accounts/manage/ManageAccountsPage.tsx b/apps/wallet/src/ui/app/pages/accounts/manage/ManageAccountsPage.tsx deleted file mode 100644 index df27c3d31ca60..0000000000000 --- a/apps/wallet/src/ui/app/pages/accounts/manage/ManageAccountsPage.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { type AccountType } from '_src/background/accounts/Account'; -import { useInitializedGuard } from '_src/ui/app/hooks'; -import { useAccountGroups } from '_src/ui/app/hooks/useAccountGroups'; -import { useNavigate } from 'react-router-dom'; - -import Overlay from '../../../components/overlay'; -import { AccountGroup } from './AccountGroup'; - -export function ManageAccountsPage() { - const navigate = useNavigate(); - const groupedAccounts = useAccountGroups(); - useInitializedGuard(true); - return ( - navigate('/home')}> -
    - {Object.entries(groupedAccounts).map(([type, accountGroups]) => - Object.entries(accountGroups).map(([key, accounts]) => { - return ( - - ); - }), - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/SignMessageRequest.tsx b/apps/wallet/src/ui/app/pages/approval-request/SignMessageRequest.tsx deleted file mode 100644 index 04017de85e669..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/SignMessageRequest.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SignMessageApprovalRequest } from '_payloads/transactions/ApprovalRequest'; -import { toUtf8OrB64 } from '_src/shared/utils'; -import { useMemo } from 'react'; - -import { UserApproveContainer } from '../../components/user-approve-container'; -import { useAppDispatch } from '../../hooks'; -import { useAccountByAddress } from '../../hooks/useAccountByAddress'; -import { useQredoTransaction } from '../../hooks/useQredoTransaction'; -import { useSigner } from '../../hooks/useSigner'; -import { respondToTransactionRequest } from '../../redux/slices/transaction-requests'; -import { Heading } from '../../shared/heading'; -import { PageMainLayoutTitle } from '../../shared/page-main-layout/PageMainLayoutTitle'; -import { Text } from '../../shared/text'; - -export type SignMessageRequestProps = { - request: SignMessageApprovalRequest; -}; - -export function SignMessageRequest({ request }: SignMessageRequestProps) { - const { message, type } = useMemo(() => toUtf8OrB64(request.tx.message), [request.tx.message]); - const { data: account } = useAccountByAddress(request.tx.accountAddress); - const signer = useSigner(account); - const dispatch = useAppDispatch(); - const { clientIdentifier, notificationModal } = useQredoTransaction(true); - - return ( - { - if (!signer) { - return; - } - await dispatch( - respondToTransactionRequest({ - txRequestID: request.id, - approved, - signer, - clientIdentifier, - }), - ); - }} - address={request.tx.accountAddress} - scrollable - blended - checkAccountLock - > - -
    - - Message You Are Signing - -
    -
    -
    - - {message} - -
    -
    - {notificationModal} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/index.tsx b/apps/wallet/src/ui/app/pages/approval-request/index.tsx deleted file mode 100644 index aebbe4c4f01a7..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { - isSignMessageApprovalRequest, - isTransactionApprovalRequest, -} from '_payloads/transactions/ApprovalRequest'; -import { useEffect, useMemo } from 'react'; -import { useParams } from 'react-router-dom'; - -import Loading from '../../components/loading'; -import { useAppSelector } from '../../hooks'; -import { type RootState } from '../../redux/RootReducer'; -import { txRequestsSelectors } from '../../redux/slices/transaction-requests'; -import { SignMessageRequest } from './SignMessageRequest'; -import { TransactionRequest } from './transaction-request'; - -export function ApprovalRequestPage() { - const { requestID } = useParams(); - const requestSelector = useMemo( - () => (state: RootState) => - (requestID && txRequestsSelectors.selectById(state, requestID)) || null, - [requestID], - ); - const request = useAppSelector(requestSelector); - const requestsLoading = useAppSelector( - ({ transactionRequests }) => !transactionRequests.initialized, - ); - useEffect(() => { - if (!requestsLoading && (!request || (request && request.approved !== null))) { - window.close(); - } - }, [requestsLoading, request]); - return ( - - {request ? ( - isSignMessageApprovalRequest(request) ? ( - - ) : isTransactionApprovalRequest(request) ? ( - - ) : null - ) : null} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/DescriptionList.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/DescriptionList.tsx deleted file mode 100644 index 1ad89528d8d1f..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/DescriptionList.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -/** - * TODO: Generalize this file into shared components. - */ - -import type { ReactNode } from 'react'; - -export interface DescriptionItemProps { - title: string | ReactNode; - children: ReactNode; -} - -export function DescriptionItem({ title, children }: DescriptionItemProps) { - return ( -
    -
    {title}
    -
    {children}
    -
    - ); -} - -export type DescriptionListProps = { - children: ReactNode; -}; - -export function DescriptionList({ children }: DescriptionListProps) { - return
    {children}
    ; -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx deleted file mode 100644 index cd997b7ae7184..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useTransactionData, useTransactionGasBudget } from '_src/ui/app/hooks'; -import { GAS_SYMBOL } from '_src/ui/app/redux/slices/sui-objects/Coin'; -import { type Transaction } from '@mysten/sui/transactions'; -import { formatAddress } from '@mysten/sui/utils'; - -import { DescriptionItem, DescriptionList } from './DescriptionList'; -import { SummaryCard } from './SummaryCard'; - -interface Props { - sender?: string; - transaction: Transaction; -} - -export function GasFees({ sender, transaction }: Props) { - const { data: transactionData } = useTransactionData(sender, transaction); - const { data: gasBudget, isPending, isError } = useTransactionGasBudget(sender, transaction); - const isSponsored = - transactionData?.gasData.owner && transactionData.sender !== transactionData.gasData.owner; - return ( - - Sponsored -
    - ) : null - } - initialExpanded - > - - - {isPending - ? 'Estimating...' - : isError - ? 'Gas estimation failed' - : `${isSponsored ? 0 : gasBudget} ${GAS_SYMBOL}`} - - {isSponsored && ( - <> - - {gasBudget ? `${gasBudget} ${GAS_SYMBOL}` : '-'} - - - {formatAddress(transactionData!.gasData.owner!)} - - - )} - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/MiniNFT.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/MiniNFT.tsx deleted file mode 100644 index 375f16a63fe19..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/MiniNFT.tsx +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import st from './TransactionRequest.module.scss'; - -export type MiniNFTProps = { - size?: 'xs' | 'sm'; - url: string; - name?: string | null; -}; - -export function MiniNFT({ size = 'sm', url, name }: MiniNFTProps) { - const sizes = size === 'xs' ? st.nftImageTiny : st.nftImageSmall; - return {name; -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/SummaryCard.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/SummaryCard.tsx deleted file mode 100644 index 86793cceb7a58..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/SummaryCard.tsx +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ChevronDown16, ChevronRight16 } from '@mysten/icons'; -import clsx from 'clsx'; -import { useState, type ReactNode } from 'react'; - -import { Text } from '../../../shared/text'; - -type SummaryCardProps = { - header: ReactNode; - children: ReactNode; - badge?: ReactNode; - initialExpanded?: boolean; -}; - -export function SummaryCard({ - children, - header, - badge, - initialExpanded = false, -}: SummaryCardProps) { - const [expanded, setExpanded] = useState(initialExpanded); - - return ( -
    - - {expanded &&
    {children}
    } -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx deleted file mode 100644 index b232413b7ebce..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import { ChevronDown12, ChevronRight12 } from '@mysten/icons'; -import { type Argument, type Commands, type TransactionData } from '@mysten/sui/transactions'; -import { toBase64 } from '@mysten/sui/utils'; -import { useState } from 'react'; - -type TransactionType = TransactionData['commands'][0]; -type MakeMoveVecTransaction = ReturnType<(typeof Commands)['MakeMoveVec']>; -type PublishTransaction = ReturnType<(typeof Commands)['Publish']>; - -function convertCommandArgumentToString( - arg: - | null - | string - | number - | string[] - | number[] - | Argument - | Argument[] - | MakeMoveVecTransaction['MakeMoveVec']['type'] - | PublishTransaction['Publish']['modules'], -): string | null { - if (!arg) return null; - - if (typeof arg === 'string' || typeof arg === 'number') return String(arg); - - if (typeof arg === 'object' && 'None' in arg) { - return null; - } - - if (Array.isArray(arg)) { - // Publish transaction special casing: - if (typeof arg[0] === 'number') { - return toBase64(new Uint8Array(arg as number[])); - } - - return `[${arg.map((argVal) => convertCommandArgumentToString(argVal)).join(', ')}]`; - } - - switch (arg.$kind) { - case 'GasCoin': - return 'GasCoin'; - case 'Input': - return `Input(${arg.Input})`; - case 'Result': - return `Result(${arg.Result})`; - case 'NestedResult': - return `NestedResult(${arg.NestedResult[0]}, ${arg.NestedResult[1]})`; - default: - // eslint-disable-next-line no-console - console.warn('Unexpected command argument type.', arg); - return null; - } -} - -function convertCommandToString(command: TransactionType) { - let normalizedCommand; - switch (command.$kind) { - case 'MoveCall': - normalizedCommand = { - kind: 'MoveCall', - ...command.MoveCall, - typeArguments: command.MoveCall.typeArguments, - }; - break; - case 'MakeMoveVec': - normalizedCommand = { - kind: 'MakeMoveVec', - type: command.MakeMoveVec.type, - elements: command.MakeMoveVec.elements, - }; - break; - case 'MergeCoins': - normalizedCommand = { - kind: 'MergeCoins', - destination: command.MergeCoins.destination, - sources: command.MergeCoins.sources, - }; - break; - case 'TransferObjects': - normalizedCommand = { - kind: 'TransferObjects', - objects: command.TransferObjects.objects, - address: command.TransferObjects.address, - }; - break; - case 'SplitCoins': - normalizedCommand = { - kind: 'SplitCoins', - coin: command.SplitCoins.coin, - amounts: command.SplitCoins.amounts, - }; - break; - case 'Publish': - normalizedCommand = { - kind: 'Publish', - modules: command.Publish.modules, - dependencies: command.Publish.dependencies, - }; - break; - case 'Upgrade': - normalizedCommand = { - kind: 'Upgrade', - modules: command.Upgrade.modules, - dependencies: command.Upgrade.dependencies, - packageId: command.Upgrade.package, - ticket: command.Upgrade.ticket, - }; - break; - case '$Intent': { - throw new Error('TransactionIntent is not supported'); - } - } - - const commandArguments = Object.entries(normalizedCommand); - return commandArguments - .map(([key, value]) => { - const stringValue = convertCommandArgumentToString(value); - - if (!stringValue) return null; - - return `${key}: ${stringValue}`; - }) - .filter(Boolean) - .join(', '); -} - -interface CommandProps { - command: TransactionType; -} - -export function Command({ command }: CommandProps) { - const [expanded, setExpanded] = useState(true); - - return ( -
    - - - {expanded && ( -
    - ({convertCommandToString(command)}) -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx deleted file mode 100644 index 1e35d77928f0e..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import ExplorerLink from '_src/ui/app/components/explorer-link'; -import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; -import { Text } from '_src/ui/app/shared/text'; -import { type TransactionInput } from '@mysten/sui/transactions'; -import { formatAddress } from '@mysten/sui/utils'; - -interface InputProps { - input: TransactionInput; -} - -export function Input({ input }: InputProps) { - const { objectId } = - input?.Object?.ImmOrOwnedObject ?? - input?.Object?.SharedObject ?? - input.Object?.Receiving! ?? - {}; - - return ( -
    - - {input.Pure ? ( - `${input.Pure.bytes}` - ) : input.Object ? ( - - {formatAddress(objectId)} - - ) : ( - 'Unknown input value' - )} - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx deleted file mode 100644 index 4511c059d1463..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useTransactionData } from '_src/ui/app/hooks'; -import { Tab as HeadlessTab, type TabProps } from '@headlessui/react'; -import { type Transaction } from '@mysten/sui/transactions'; - -import { SummaryCard } from '../SummaryCard'; -import { Command } from './Command'; -import { Input } from './Input'; - -interface Props { - sender?: string; - transaction: Transaction; -} - -const Tab = (props: TabProps<'div'>) => ( - -); - -export function TransactionDetails({ sender, transaction }: Props) { - const { data: transactionData, isPending, isError } = useTransactionData(sender, transaction); - if (transactionData?.commands.length === 0 && transactionData.inputs.length === 0) { - return null; - } - return ( - - {isPending || isError ? ( -
    - {isPending ? 'Gathering data...' : "Couldn't gather data"} -
    - ) : transactionData ? ( -
    - - - {!!transactionData.commands.length && Commands} - {!!transactionData.inputs.length && Inputs} - - - {!!transactionData.commands.length && ( - - {/* TODO: Rename components: */} - {transactionData.commands.map((command, index) => ( - - ))} - - )} - {!!transactionData.inputs.length && ( - - {transactionData.inputs.map((input, index) => ( - - ))} - - )} - - -
    - ) : ( - '' - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionRequest.module.scss b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionRequest.module.scss deleted file mode 100644 index fbcf37b528d92..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionRequest.module.scss +++ /dev/null @@ -1,237 +0,0 @@ -@use '_values/colors'; -@use '_utils'; - -.card { - background: colors.$white; - border-radius: 15px; - border: 1px solid colors.$card-border-color; - - .header { - background: #e1f3ff80; - height: 31px; - display: flex; - justify-content: center; - color: colors.$sui-blue-steel-darker; - padding: 10px 0; - font-weight: 600; - font-size: 11px; - line-height: 100%; - text-transform: uppercase; - border-radius: 15px 15px 0 0; - letter-spacing: 0.05em; - } - - .transparent-header { - background: none; - display: flex; - border-bottom: 1px solid colors.$gray-45; - margin: 0 15px; - flex-direction: row; - justify-content: space-between; - font-size: 13px; - padding: 12px 0; - height: auto; - line-height: 100%; - text-transform: capitalize; - letter-spacing: 0; - - .tx-type-header-status { - font-weight: 600; - color: colors.$sui-blue-steel-dark; - } - } - - .card-footer { - width: 100%; - display: flex; - justify-content: space-between; - padding-top: 10px; - color: colors.$sui-blue-steel-dark; - - @include utils.typography('Primary/BodySmall-M'); - } -} - -.content-wrapper { - padding: 15px; - display: flex; - flex-direction: column; - - :first-child { - padding-top: 0; - } -} - -.content { - display: flex; - flex-direction: column; - align-content: center; - gap: 8px; - border-bottom: 1px solid colors.$gray-45; - padding: 12px 0; - - &:last-of-type { - border-bottom: none; - } - - &:first-of-type { - padding-top: 0; - padding-bottom: 0; - } -} - -.row { - display: flex; - justify-content: space-between; - gap: 10px; - font-weight: 500; - font-size: 13px; - line-height: 100%; - - .label { - color: colors.$sui-blue-steel-dark; - display: flex; - justify-content: flex-start; - } - - .value { - color: colors.$gray-90; - font-weight: 600; - word-break: break-all; - padding: 0; - display: flex; - justify-content: flex-end; - text-align: right; - } -} - -.tabs { - font-weight: 600; - font-size: 14px; - line-height: 17px; - display: flex; - gap: 22px; - border-bottom: 1px solid colors.$gray-45; - - .tab { - cursor: pointer; - background: none; - border: none; - padding: 8px 0; - padding-top: 0; - margin-bottom: -1px; - color: colors.$sui-blue-steel-darker; - font-weight: 600; - font-size: 14px; - line-height: 100%; - border-bottom: 1px solid colors.$gray-45; - - &.active { - color: colors.$cta-blue-hover; - border-color: colors.$cta-blue-hover; - } - } -} - -.objects { - display: flex; - flex-direction: column; - gap: 20px; - margin-top: 6px; -} - -.object-name { - font-weight: 500; - font-size: 13px; - line-height: 17px; - color: colors.$sui-blue-steel-dark; - font-family: 'Red Hat Mono Variable', ui-monospace, monospace; - word-break: break-all; -} - -.object-id { - font-weight: 500; - font-size: 13px; - line-height: 17px; - font-family: 'Red Hat Mono Variable', ui-monospace, monospace; - color: colors.$sui-dark-blue; - text-decoration: none; -} - -.tx-info { - display: flex; - flex-direction: column; - gap: 15px; -} - -.deserializing { - min-height: 450px; -} - -.nft-image-tiny { - width: 12px; - display: block; -} - -.nft-image-small { - width: 36px; - display: block; -} - -.origin { - margin-bottom: 10px; - font-size: 13px; - line-height: 100%; - font-weight: 500; - text-decoration: none; - text-transform: lowercase; - color: colors.$sui-dark-blue; -} - -.permissions-content { - display: flex; - flex-direction: row; - gap: 8px; - justify-content: space-between; -} - -.package-info { - border: 1px solid colors.$gray-50; - - .label, - .value { - @include utils.typography('Primary/BodySmall-M'); - - display: block; - - &::first-letter { - text-transform: uppercase; - } - } - - .label { - color: colors.$sui-blue-steel-dark; - } - - .value { - color: colors.$sui-blue-steel-darker; - } - - .content-wrapper { - padding: 12px 15px; - } - - .content { - gap: 12px; - } -} - -.owner-address { - font-family: 'Red Hat Mono Variable', ui-monospace, monospace; -} - -.permissions-content-label { - display: flex; - flex-direction: column; - gap: 2px; -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx deleted file mode 100644 index a9bea2867c81d..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -// import { Transaction } from '@mysten/sui'; -import { UserApproveContainer } from '_components/user-approve-container'; -import { useAppDispatch, useTransactionData, useTransactionDryRun } from '_hooks'; -import { type TransactionApprovalRequest } from '_payloads/transactions/ApprovalRequest'; -import { respondToTransactionRequest } from '_redux/slices/transaction-requests'; -import { ampli } from '_src/shared/analytics/ampli'; -import { useAccountByAddress } from '_src/ui/app/hooks/useAccountByAddress'; -import { useQredoTransaction } from '_src/ui/app/hooks/useQredoTransaction'; -import { useRecognizedPackages } from '_src/ui/app/hooks/useRecognizedPackages'; -import { useSigner } from '_src/ui/app/hooks/useSigner'; -import { PageMainLayoutTitle } from '_src/ui/app/shared/page-main-layout/PageMainLayoutTitle'; -import { TransactionSummary } from '_src/ui/app/shared/transaction-summary'; -import { useTransactionSummary } from '@mysten/core'; -import { Transaction } from '@mysten/sui/transactions'; -import { useMemo, useState } from 'react'; - -import { ConfirmationModal } from '../../../shared/ConfirmationModal'; -import { GasFees } from './GasFees'; -import { TransactionDetails } from './TransactionDetails'; - -export type TransactionRequestProps = { - txRequest: TransactionApprovalRequest; -}; - -// Some applications require *a lot* of transactions to interact with, and this -// eats up our analytics event quota. As a short-term solution so we don't have -// to stop tracking this event entirely, we'll just manually exclude application -// origins with this list -const appOriginsToExcludeFromAnalytics = ['https://sui8192.ethoswallet.xyz']; - -export function TransactionRequest({ txRequest }: TransactionRequestProps) { - const addressForTransaction = txRequest.tx.account; - const { data: accountForTransaction } = useAccountByAddress(addressForTransaction); - const signer = useSigner(accountForTransaction); - const dispatch = useAppDispatch(); - const transaction = useMemo(() => { - const tx = Transaction.from(txRequest.tx.data); - if (addressForTransaction) { - tx.setSenderIfNotSet(addressForTransaction); - } - return tx; - }, [txRequest.tx.data, addressForTransaction]); - const { isPending, isError } = useTransactionData(addressForTransaction, transaction); - const [isConfirmationVisible, setConfirmationVisible] = useState(false); - - const { - data, - isError: isDryRunError, - isPending: isDryRunLoading, - } = useTransactionDryRun(addressForTransaction, transaction); - const recognizedPackagesList = useRecognizedPackages(); - - const summary = useTransactionSummary({ - transaction: data, - currentAddress: addressForTransaction, - recognizedPackagesList, - }); - const { clientIdentifier, notificationModal } = useQredoTransaction(true); - if (!signer) { - return null; - } - return ( - <> - { - if (isPending) return; - if (approved && isError) { - setConfirmationVisible(true); - return; - } - await dispatch( - respondToTransactionRequest({ - approved, - txRequestID: txRequest.id, - signer, - clientIdentifier, - }), - ); - if (!appOriginsToExcludeFromAnalytics.includes(txRequest.origin)) { - ampli.respondedToTransactionRequest({ - applicationUrl: txRequest.origin, - approvedTransaction: approved, - receivedFailureWarning: false, - type: txRequest.tx.justSign ? 'sign' : 'sign-and-execute', - }); - } - }} - address={addressForTransaction} - approveLoading={isPending || isConfirmationVisible} - checkAccountLock - > - -
    -
    - -
    -
    -
    - - -
    -
    -
    -
    - { - await dispatch( - respondToTransactionRequest({ - approved: isConfirmed, - txRequestID: txRequest.id, - signer, - clientIdentifier, - }), - ); - ampli.respondedToTransactionRequest({ - applicationUrl: txRequest.origin, - approvedTransaction: isConfirmed, - receivedFailureWarning: true, - type: txRequest.tx.justSign ? 'sign' : 'sign-and-execute', - }); - setConfirmationVisible(false); - }} - /> - {notificationModal} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts deleted file mode 100644 index 589b35ce40cdd..0000000000000 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type SuiMoveNormalizedType } from '@mysten/sui/client'; - -export interface TypeReference { - address: string; - module: string; - name: string; - typeArguments: SuiMoveNormalizedType[]; -} - -export const TX_CONTEXT_TYPE = '0x2::tx_context::TxContext'; - -/** Takes a normalized move type and returns the address information contained within it */ -export function unwrapTypeReference(type: SuiMoveNormalizedType): null | TypeReference { - if (typeof type === 'object') { - if ('Struct' in type) { - return type.Struct; - } - if ('Reference' in type) { - return unwrapTypeReference(type.Reference); - } - if ('MutableReference' in type) { - return unwrapTypeReference(type.MutableReference); - } - if ('Vector' in type) { - return unwrapTypeReference(type.Vector); - } - } - return null; -} diff --git a/apps/wallet/src/ui/app/pages/home/apps/AppsPage.module.scss b/apps/wallet/src/ui/app/pages/home/apps/AppsPage.module.scss deleted file mode 100644 index ed35ffbff719f..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/apps/AppsPage.module.scss +++ /dev/null @@ -1,15 +0,0 @@ -@use '_utils'; -@use '_values/colors'; - -.active-section-title { - @include utils.typography('table/text-xs'); - - text-transform: uppercase; -} - -.container { - display: flex; - flex-flow: column nowrap; - overflow-x: visible; - height: 100%; -} diff --git a/apps/wallet/src/ui/app/pages/home/apps/index.tsx b/apps/wallet/src/ui/app/pages/home/apps/index.tsx deleted file mode 100644 index b70af24791fa8..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/apps/index.tsx +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Content } from '_app/shared/bottom-menu-layout'; -import FiltersPortal from '_components/filters-tags'; -import AppsPlayGround, { ConnectedAppsCard } from '_components/sui-apps'; -import { getFromSessionStorage, setToSessionStorage } from '_src/background/storage-utils'; -import { FEATURES } from '_src/shared/experimentation/features'; -import type { DAppEntry } from '_src/ui/app/components/sui-apps/SuiApp'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { useFeature } from '@growthbook/growthbook-react'; -import { useEffect } from 'react'; -import { Route, Routes, useNavigate } from 'react-router-dom'; - -import st from './AppsPage.module.scss'; - -const APPS_PAGE_NAVIGATION = 'APPS_PAGE_NAVIGATION'; - -type FilterTag = { - name: string; - link: string; -}; - -function AppsPage() { - const navigate = useNavigate(); - - const defaultFilterTags: FilterTag[] = [ - { - name: 'Connections', - link: 'apps/connected', - }, - { - name: 'All', - link: 'apps', - }, - ]; - const ecosystemApps = useFeature(FEATURES.WALLET_DAPPS).value ?? []; - - const uniqueAppTags = Array.from(new Set(ecosystemApps.flatMap((app) => app.tags))) - .map((tag) => ({ - name: tag, - // The tag subroute is used to get around the NavLink limitation with reading query params - // Enables active route highlighting without excessive overhead - link: `apps/${tag}`, - })) - .sort((a, b) => a.name.localeCompare(b.name)); - - const allFilterTags = [...defaultFilterTags, ...uniqueAppTags]; - - useEffect(() => { - getFromSessionStorage(APPS_PAGE_NAVIGATION).then((activeTagLink) => { - if (activeTagLink) { - navigate(`/${activeTagLink}`); - - const element = document.getElementById(activeTagLink); - - if (element) { - element.scrollIntoView(); - } - } - }); - }, [navigate]); - - const handleFiltersPortalClick = async (tag: FilterTag) => { - await setToSessionStorage(APPS_PAGE_NAVIGATION, tag.link); - }; - - if (useUnlockedGuard()) { - return null; - } - - return ( -
    - -
    - - - } /> - } /> - -
    -
    -
    - ); -} - -export default AppsPage; diff --git a/apps/wallet/src/ui/app/pages/home/assets/index.tsx b/apps/wallet/src/ui/app/pages/home/assets/index.tsx deleted file mode 100644 index c676592a2b30c..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/assets/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { Route, Routes } from 'react-router-dom'; - -import { HiddenAssetsPage, NftsPage } from '..'; -import { HiddenAssetsProvider } from '../hidden-assets/HiddenAssetsProvider'; - -function AssetsPage() { - if (useUnlockedGuard()) { - return null; - } - return ( - - - } /> - } /> - - - ); -} - -export default AssetsPage; diff --git a/apps/wallet/src/ui/app/pages/home/hidden-assets/HiddenAssetsProvider.tsx b/apps/wallet/src/ui/app/pages/home/hidden-assets/HiddenAssetsProvider.tsx deleted file mode 100644 index e1396de48aec8..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/hidden-assets/HiddenAssetsProvider.tsx +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import { Check12 } from '@mysten/icons'; -import { get, set } from 'idb-keyval'; -import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from 'react'; -import { toast } from 'react-hot-toast'; - -import { Link as InlineLink } from '../../../shared/Link'; - -const HIDDEN_ASSET_IDS = 'hidden-asset-ids'; - -interface HiddenAssetContext { - hiddenAssetIds: string[]; - setHiddenAssetIds: (hiddenAssetIds: string[]) => void; - hideAsset: (assetId: string) => void; - showAsset: (assetId: string) => void; -} - -export const HiddenAssetsContext = createContext({ - hiddenAssetIds: [], - setHiddenAssetIds: () => {}, - hideAsset: () => {}, - showAsset: () => {}, -}); - -export const HiddenAssetsProvider = ({ children }: { children: ReactNode }) => { - const [hiddenAssetIds, setHiddenAssetIds] = useState([]); - - useEffect(() => { - (async () => { - const hiddenAssets = await get(HIDDEN_ASSET_IDS); - if (hiddenAssets) { - setHiddenAssetIds(hiddenAssets); - } - })(); - }, []); - - const hideAssetId = useCallback( - async (newAssetId: string) => { - if (hiddenAssetIds.includes(newAssetId)) return; - - const newHiddenAssetIds = [...hiddenAssetIds, newAssetId]; - setHiddenAssetIds(newHiddenAssetIds); - await set(HIDDEN_ASSET_IDS, newHiddenAssetIds); - - const undoHideAsset = async (assetId: string) => { - try { - let updatedHiddenAssetIds; - setHiddenAssetIds((prevIds) => { - updatedHiddenAssetIds = prevIds.filter((id) => id !== assetId); - return updatedHiddenAssetIds; - }); - await set(HIDDEN_ASSET_IDS, updatedHiddenAssetIds); - } catch (error) { - // Handle any error that occurred during the unhide process - toast.error('Failed to unhide asset.'); - // Restore the asset ID back to the hidden asset IDs list - setHiddenAssetIds([...hiddenAssetIds, assetId]); - await set(HIDDEN_ASSET_IDS, hiddenAssetIds); - } - }; - - const showAssetHiddenToast = async (objectId: string) => { - toast.custom( - (t) => ( -
    -
    - -
    { - toast.dismiss(t.id); - }} - > - - Moved to - - } - text="Hidden Assets" - onClick={() => toast.dismiss(t.id)} - /> -
    -
    - -
    - { - undoHideAsset(objectId); - toast.dismiss(t.id); - }} - color="hero" - weight="medium" - text="UNDO" - /> -
    -
    - ), - { - duration: 4000, - }, - ); - }; - - showAssetHiddenToast(newAssetId); - }, - [hiddenAssetIds], - ); - - const showAssetId = useCallback( - async (newAssetId: string) => { - if (!hiddenAssetIds.includes(newAssetId)) return; - - try { - const updatedHiddenAssetIds = hiddenAssetIds.filter((id) => id !== newAssetId); - setHiddenAssetIds(updatedHiddenAssetIds); - await set(HIDDEN_ASSET_IDS, updatedHiddenAssetIds); - } catch (error) { - // Handle any error that occurred during the unhide process - toast.error('Failed to show asset.'); - // Restore the asset ID back to the hidden asset IDs list - setHiddenAssetIds([...hiddenAssetIds, newAssetId]); - await set(HIDDEN_ASSET_IDS, hiddenAssetIds); - } - - const undoShowAsset = async (assetId: string) => { - let newHiddenAssetIds; - setHiddenAssetIds((prevIds) => { - return (newHiddenAssetIds = [...prevIds, assetId]); - }); - await set(HIDDEN_ASSET_IDS, newHiddenAssetIds); - }; - - const assetShownToast = async (objectId: string) => { - toast.custom( - (t) => ( -
    -
    - -
    { - toast.dismiss(t.id); - }} - > - - Moved to - - } - text="Visual Assets" - onClick={() => toast.dismiss(t.id)} - /> -
    -
    - -
    - { - undoShowAsset(objectId); - toast.dismiss(t.id); - }} - color="hero" - weight="medium" - text="UNDO" - /> -
    -
    - ), - { - duration: 4000, - }, - ); - }; - - assetShownToast(newAssetId); - }, - [hiddenAssetIds], - ); - - const showAsset = (objectId: string) => { - showAssetId(objectId); - }; - - return ( - - {children} - - ); -}; - -export const useHiddenAssets = () => { - return useContext(HiddenAssetsContext); -}; diff --git a/apps/wallet/src/ui/app/pages/home/hidden-assets/index.tsx b/apps/wallet/src/ui/app/pages/home/hidden-assets/index.tsx deleted file mode 100644 index 19d191b303b9b..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/hidden-assets/index.tsx +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useBlockedObjectList } from '_app/hooks/useBlockedObjectList'; -import Alert from '_components/alert'; -import { ErrorBoundary } from '_components/error-boundary'; -import Loading from '_components/loading'; -import LoadingSpinner from '_components/loading/LoadingIndicator'; -import { NFTDisplayCard } from '_components/nft-display'; -import { ampli } from '_src/shared/analytics/ampli'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import { getKioskIdFromOwnerCap, isKioskOwnerToken, useMultiGetObjects } from '@mysten/core'; -import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { EyeClose16 } from '@mysten/icons'; -import { normalizeStructTag } from '@mysten/sui/utils'; -import { keepPreviousData } from '@tanstack/react-query'; -import { useMemo } from 'react'; -import { Link } from 'react-router-dom'; - -import { useHiddenAssets } from './HiddenAssetsProvider'; - -function HiddenNftsPage() { - const { hiddenAssetIds, showAsset } = useHiddenAssets(); - const kioskClient = useKioskClient(); - const { data: blockedObjectList } = useBlockedObjectList(); - - const { data, isLoading, isPending, isError, error } = useMultiGetObjects( - hiddenAssetIds, - { - showDisplay: true, - showType: true, - }, - { placeholderData: keepPreviousData }, - ); - - const filteredAndSortedNfts = useMemo(() => { - const hiddenNfts = - data?.flatMap((data) => { - return { - data: data.data, - display: data.data?.display?.data, - }; - }) || []; - - return hiddenNfts - ?.filter((nft) => nft.data && hiddenAssetIds.includes(nft?.data?.objectId)) - .filter((nft) => { - if (!nft.data?.type) { - return true; - } - const normalizedType = normalizeStructTag(nft.data.type); - return !blockedObjectList?.includes(normalizedType); - }) - .sort((nftA, nftB) => { - let nameA = nftA.display?.name || ''; - let nameB = nftB.display?.name || ''; - - if (nameA < nameB) { - return -1; - } else if (nameA > nameB) { - return 1; - } - return 0; - }); - }, [hiddenAssetIds, data, blockedObjectList]); - - if (isLoading) { - return ( -
    - -
    - ); - } - - return ( -
    - - - {isError ? ( - -
    - Sync error (data might be outdated) -
    - {(error as Error).message} -
    - ) : null} - {filteredAndSortedNfts?.length ? ( -
    - {filteredAndSortedNfts.map((nft) => { - const { objectId, type } = nft.data!; - return ( -
    - { - ampli.clickedCollectibleCard({ - objectId, - collectibleType: type!, - }); - }} - className="no-underline relative truncate" - > - - - - -
    -
    -
    - ); - })} -
    - ) : ( -
    - No Assets found -
    - )} -
    -
    - ); -} - -export default HiddenNftsPage; diff --git a/apps/wallet/src/ui/app/pages/home/index.tsx b/apps/wallet/src/ui/app/pages/home/index.tsx deleted file mode 100644 index 367c9e52703f1..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Loading from '_components/loading'; -import { useInitializedGuard } from '_hooks'; -import { useSetGrowthbookAttributes } from '_shared/utils'; -import { PageMainLayout } from '_src/ui/app/shared/page-main-layout/PageMainLayout'; -import { Outlet } from 'react-router-dom'; - -interface Props { - disableNavigation?: boolean; -} - -const HomePage = ({ disableNavigation }: Props) => { - const initChecking = useInitializedGuard(true); - const guardChecking = initChecking; - - useSetGrowthbookAttributes(); - return ( - - - - - - ); -}; - -export default HomePage; -export { default as NftsPage } from './nfts'; -export { default as HiddenAssetsPage } from './hidden-assets'; -export { default as AssetsPage } from './assets'; -export { default as TokensPage } from './tokens'; -export { default as TransactionBlocksPage } from './transactions'; -export { default as TransferCoinPage } from './transfer-coin'; -export { default as NFTDetailsPage } from './nft-details'; -export { default as NftTransferPage } from './nft-transfer'; -export { default as KioskDetailsPage } from './kiosk-details'; -export { default as ReceiptPage } from './receipt'; -export { default as CoinsSelectorPage } from './transfer-coin/CoinSelector'; -export { default as AppsPage } from './apps'; -export { Onramp as OnrampPage } from './onramp'; diff --git a/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx b/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx deleted file mode 100644 index 86f3d2272550a..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ButtonOrLink } from '_app/shared/utils/ButtonOrLink'; -import { ampli } from '_src/shared/analytics/ampli'; -import ExternalLink from '_src/ui/app/components/external-link'; -import { Text } from '_src/ui/app/shared/text'; -import { X32 } from '@mysten/icons'; -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { Portal } from '../../../shared/Portal'; - -export type InterstitialConfig = { - enabled: boolean; - dismissKey?: string; - imageUrl?: string; - buttonText?: string; - bannerUrl?: string; -}; - -interface InterstitialProps extends InterstitialConfig { - onClose: () => void; -} - -const setInterstitialDismissed = (dismissKey: string) => localStorage.setItem(dismissKey, 'true'); - -function Interstitial({ - enabled, - dismissKey, - imageUrl, - bannerUrl, - buttonText, - onClose, -}: InterstitialProps) { - const navigate = useNavigate(); - - useEffect(() => { - const t = setTimeout(setInterstitialDismissed, 1000); - return () => clearTimeout(t); - }, []); - - const closeInterstitial = (dismissKey?: string) => { - if (dismissKey) { - setInterstitialDismissed(dismissKey); - } - onClose(); - navigate('/apps'); - }; - - const onClick = () => { - ampli.clickedBullsharkQuestsCta({ sourceFlow: 'Interstitial' }); - closeInterstitial(); - }; - - if (!enabled) { - return null; - } - - return ( - -
    - - {bannerUrl && ( - - interstitial-banner - - )} - - - {buttonText || 'Join for a chance to win'} - - -
    -
    - ); -} - -export default Interstitial; diff --git a/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx b/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx deleted file mode 100644 index 58bfa561c1a85..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import { ErrorBoundary } from '_src/ui/app/components/error-boundary'; -import ExplorerLink from '_src/ui/app/components/explorer-link'; -import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; -import { LabelValueItem } from '_src/ui/app/components/LabelValueItem'; -import { LabelValuesContainer } from '_src/ui/app/components/LabelValuesContainer'; -import Loading from '_src/ui/app/components/loading'; -import { NFTDisplayCard } from '_src/ui/app/components/nft-display'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { Collapsible } from '_src/ui/app/shared/collapse'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import { useGetKioskContents } from '@mysten/core'; -import { formatAddress } from '@mysten/sui/utils'; -import { Link, useSearchParams } from 'react-router-dom'; - -function KioskDetailsPage() { - const [searchParams] = useSearchParams(); - const kioskId = searchParams.get('kioskId'); - const accountAddress = useActiveAddress(); - const { data: kioskData, isPending } = useGetKioskContents(accountAddress); - const kiosk = kioskData?.kiosks.get(kioskId!); - const items = kiosk?.items; - - if (useUnlockedGuard()) { - return null; - } - - return ( -
    - - - {!items?.length ? ( -
    - Kiosk is empty -
    - ) : ( - <> -
    - {items.map((item) => ( - - - - - - ))} -
    - - )} - - - - - {formatAddress(kioskId!)} - - } - /> - - -
    -
    - ); -} - -export default KioskDetailsPage; diff --git a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx b/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx deleted file mode 100644 index 8bde8d0ecb029..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import { Button } from '_app/shared/ButtonUI'; -import { Collapsible } from '_app/shared/collapse'; -import { Link } from '_app/shared/Link'; -import { ExplorerLinkType } from '_components/explorer-link/ExplorerLinkType'; -import { LabelValueItem } from '_components/LabelValueItem'; -import { LabelValuesContainer } from '_components/LabelValuesContainer'; -import Loading from '_components/loading'; -import { NFTDisplayCard } from '_components/nft-display'; -import { useGetNFTMeta, useNFTBasicData, useOwnedNFT } from '_hooks'; -import { useBuyNLargeAssets } from '_src/ui/app/components/buynlarge/useBuyNLargeAssets'; -import { useExplorerLink } from '_src/ui/app/hooks/useExplorerLink'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import { Text } from '_src/ui/app/shared/text'; -import { useGetKioskContents } from '@mysten/core'; -import { ArrowRight16, ArrowUpRight12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import cl from 'clsx'; -import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; - -type NftFields = { - metadata?: { fields?: { attributes?: { fields?: { keys: string[]; values: string[] } } } }; -}; - -function NFTDetailsPage() { - const [searchParams] = useSearchParams(); - const nftId = searchParams.get('objectId'); - const accountAddress = useActiveAddress(); - const { data: objectData, isPending: isNftLoading } = useOwnedNFT(nftId || '', accountAddress); - const isTransferable = - !!objectData && - objectData.content?.dataType === 'moveObject' && - objectData.content?.hasPublicTransfer; - const { nftFields, fileExtensionType, filePath } = useNFTBasicData(objectData); - const address = useActiveAddress(); - const { data } = useGetKioskContents(address); - - const isContainedInKiosk = data?.lookup.get(nftId!); - const kioskItem = data?.list.find((k) => k.data?.objectId === nftId); - - const navigate = useNavigate(); - const bnl = useBuyNLargeAssets(); - - // Extract either the attributes, or use the top-level NFT fields: - const metaFields = - (nftFields as NftFields)?.metadata?.fields?.attributes?.fields || - Object.entries(nftFields ?? {}) - .filter(([key]) => key !== 'id') - .reduce( - (acc, [key, value]) => { - acc.keys.push(key); - acc.values.push(value as string); - return acc; - }, - { keys: [] as string[], values: [] as string[] }, - ); - const metaKeys: string[] = metaFields ? metaFields.keys : []; - const metaValues = metaFields ? metaFields.values : []; - const { data: nftDisplayData, isPending: isPendingDisplay } = useGetNFTMeta(nftId || ''); - const objectExplorerLink = useExplorerLink({ - type: ExplorerLinkType.object, - objectID: nftId || '', - }); - const ownerAddress = - (objectData?.owner && - typeof objectData?.owner === 'object' && - 'AddressOwner' in objectData.owner && - objectData.owner.AddressOwner) || - ''; - const ownerExplorerLink = useExplorerLink({ - type: ExplorerLinkType.address, - address: ownerAddress, - }); - const isGuardLoading = useUnlockedGuard(); - const isPending = isNftLoading || isPendingDisplay || isGuardLoading; - - const buyNLargeConfig = bnl.find((item) => item?.objectType === objectData?.type); - const isBuyNLarge = !!buyNLargeConfig; - - return ( -
    - - {objectData ? ( - <> - -
    -
    - {isBuyNLarge ? ( -
    - - {buyNLargeConfig?.sheetDescription} - -
    - ) : null} - - {nftId && !isBuyNLarge ? ( - } - /> - ) : null} -
    - {!isBuyNLarge ? ( - <> - - {ownerExplorerLink ? ( - - } - /> - ) : null} - - ) : null - } - /> - - - - - - - - - - - - {metaKeys.length ? ( - - - {metaKeys.map((aKey, idx) => ( - - ))} - - - ) : null} - - {isContainedInKiosk && kioskItem?.isLocked ? ( -
    -
    - ) : ( -
    -
    - )} - - ) : ( -
    - - ) : ( - - )} -
    -
    - ); -} - -export default NFTDetailsPage; diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx b/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx deleted file mode 100644 index 4a91d8708001a..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import BottomMenuLayout, { Content, Menu } from '_app/shared/bottom-menu-layout'; -import { Button } from '_app/shared/ButtonUI'; -import { Text } from '_app/shared/text'; -import { AddressInput } from '_components/address-input'; -import { ampli } from '_src/shared/analytics/ampli'; -import { getSignerOperationErrorMessage } from '_src/ui/app/helpers/errorMessages'; -import { useActiveAddress } from '_src/ui/app/hooks'; -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useQredoTransaction } from '_src/ui/app/hooks/useQredoTransaction'; -import { useSigner } from '_src/ui/app/hooks/useSigner'; -import { QredoActionIgnoredByUser } from '_src/ui/app/QredoSigner'; -import { useGetKioskContents, useSuiNSEnabled } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { ArrowRight16 } from '@mysten/icons'; -import { Transaction } from '@mysten/sui/transactions'; -import { isValidSuiNSName } from '@mysten/sui/utils'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { Field, Form, Formik } from 'formik'; -import { toast } from 'react-hot-toast'; -import { useNavigate } from 'react-router-dom'; - -import { useTransferKioskItem } from './useTransferKioskItem'; -import { createValidationSchema } from './validation'; - -export function TransferNFTForm({ - objectId, - objectType, -}: { - objectId: string; - objectType?: string | null; -}) { - const activeAddress = useActiveAddress(); - const rpc = useSuiClient(); - const suiNSEnabled = useSuiNSEnabled(); - const validationSchema = createValidationSchema(rpc, suiNSEnabled, activeAddress || '', objectId); - const activeAccount = useActiveAccount(); - const signer = useSigner(activeAccount); - const queryClient = useQueryClient(); - const navigate = useNavigate(); - const { clientIdentifier, notificationModal } = useQredoTransaction(); - const { data: kiosk } = useGetKioskContents(activeAddress); - const transferKioskItem = useTransferKioskItem({ objectId, objectType }); - const isContainedInKiosk = kiosk?.list.some((kioskItem) => kioskItem.data?.objectId === objectId); - - const transferNFT = useMutation({ - mutationFn: async (to: string) => { - if (!to || !signer) { - throw new Error('Missing data'); - } - - if (suiNSEnabled && isValidSuiNSName(to)) { - const address = await rpc.resolveNameServiceAddress({ - name: to, - }); - if (!address) { - throw new Error('SuiNS name not found.'); - } - to = address; - } - - if (isContainedInKiosk) { - return transferKioskItem.mutateAsync({ to, clientIdentifier }); - } - - const tx = new Transaction(); - tx.transferObjects([tx.object(objectId)], to); - - return signer.signAndExecuteTransactionBlock( - { - transactionBlock: tx, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }, - clientIdentifier, - ); - }, - onSuccess: (response) => { - queryClient.invalidateQueries({ queryKey: ['object', objectId] }); - queryClient.invalidateQueries({ queryKey: ['get-kiosk-contents'] }); - queryClient.invalidateQueries({ queryKey: ['get-owned-objects'] }); - - ampli.sentCollectible({ objectId }); - - return navigate( - `/receipt?${new URLSearchParams({ - txdigest: response.digest, - from: 'nfts', - }).toString()}`, - ); - }, - onError: (error) => { - if (error instanceof QredoActionIgnoredByUser) { - navigate('/'); - } else { - toast.error( -
    - - {getSignerOperationErrorMessage(error)} - -
    , - ); - } - }, - }); - - return ( - transferNFT.mutateAsync(to)} - > - {({ isValid }) => ( -
    - - -
    -
    - - Enter Recipient Address - -
    -
    - -
    -
    -
    - - -
    - {notificationModal} -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx b/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx deleted file mode 100644 index 87dbaf1704c25..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import Loading from '_components/loading'; -import { NFTDisplayCard } from '_components/nft-display'; -import Overlay from '_components/overlay'; -import { useOwnedNFT } from '_hooks'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { Navigate, useNavigate, useParams } from 'react-router-dom'; - -import { TransferNFTForm } from './TransferNFTForm'; - -function NftTransferPage() { - const { nftId } = useParams(); - const address = useActiveAddress(); - // verify that the nft is owned by the user and is transferable - const { data: ownedNFT, isPending: isNftLoading } = useOwnedNFT(nftId || '', address); - const navigate = useNavigate(); - const isGuardLoading = useUnlockedGuard(); - const isPending = isNftLoading || isGuardLoading; - return ( - navigate('/nfts')}> -
    - - {ownedNFT && - nftId && - ownedNFT.content?.dataType === 'moveObject' && - ownedNFT.content.hasPublicTransfer ? ( - <> -
    - -
    - - - ) : ( - - )} -
    -
    -
    - ); -} - -export default NftTransferPage; diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts b/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts deleted file mode 100644 index ea2c046c0d677..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useSigner } from '_src/ui/app/hooks/useSigner'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { - getKioskIdFromOwnerCap, - KioskTypes, - ORIGINBYTE_KIOSK_OWNER_TOKEN, - useGetKioskContents, - useGetObject, -} from '@mysten/core'; -import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { KioskTransaction } from '@mysten/kiosk'; -import { Transaction } from '@mysten/sui/transactions'; -import { useMutation } from '@tanstack/react-query'; - -const ORIGINBYTE_PACKAGE_ID = '0x083b02db943238dcea0ff0938a54a17d7575f5b48034506446e501e963391480'; - -export function useTransferKioskItem({ - objectId, - objectType, -}: { - objectId: string; - objectType?: string | null; -}) { - const client = useSuiClient(); - const activeAccount = useActiveAccount(); - const signer = useSigner(activeAccount); - const address = activeAccount?.address; - const obPackageId = useFeatureValue('kiosk-originbyte-packageid', ORIGINBYTE_PACKAGE_ID); - const { data: kioskData } = useGetKioskContents(address); // show personal kiosks too - const objectData = useGetObject(objectId); - const kioskClient = useKioskClient(); - - return useMutation({ - mutationFn: async ({ to, clientIdentifier }: { to: string; clientIdentifier?: string }) => { - if (!to || !signer || !objectType) { - throw new Error('Missing data'); - } - - const kioskId = kioskData?.lookup.get(objectId); - const kiosk = kioskData?.kiosks.get(kioskId!); - - if (!kioskId || !kiosk) { - throw new Error('Failed to find object in a kiosk'); - } - - if (kiosk.type === KioskTypes.SUI && objectData?.data?.data?.type && kiosk?.ownerCap) { - const txb = new Transaction(); - - new KioskTransaction({ transaction: txb, kioskClient, cap: kiosk.ownerCap }) - .transfer({ - itemType: objectData.data.data.type as string, - itemId: objectId, - address: to, - }) - .finalize(); - - return signer.signAndExecuteTransactionBlock( - { - transactionBlock: txb, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }, - clientIdentifier, - ); - } - - if (kiosk.type === KioskTypes.ORIGINBYTE && objectData?.data?.data?.type) { - const tx = new Transaction(); - const recipientKiosks = await client.getOwnedObjects({ - owner: to, - options: { showContent: true }, - filter: { StructType: ORIGINBYTE_KIOSK_OWNER_TOKEN }, - }); - const recipientKiosk = recipientKiosks.data[0]; - const recipientKioskId = recipientKiosk ? getKioskIdFromOwnerCap(recipientKiosk) : null; - - if (recipientKioskId) { - tx.moveCall({ - target: `${obPackageId}::ob_kiosk::p2p_transfer`, - typeArguments: [objectType], - arguments: [tx.object(kioskId), tx.object(recipientKioskId), tx.pure.id(objectId)], - }); - } else { - tx.moveCall({ - target: `${obPackageId}::ob_kiosk::p2p_transfer_and_create_target_kiosk`, - typeArguments: [objectType], - arguments: [tx.object(kioskId), tx.pure.address(to), tx.pure.id(objectId)], - }); - } - return signer.signAndExecuteTransactionBlock( - { - transactionBlock: tx, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }, - clientIdentifier, - ); - } - throw new Error('Failed to transfer object'); - }, - }); -} diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts b/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts deleted file mode 100644 index 24fcf27f75afb..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createSuiAddressValidation } from '_components/address-input/validation'; -import { type SuiClient } from '@mysten/sui/client'; -import * as Yup from 'yup'; - -export function createValidationSchema( - client: SuiClient, - suiNSEnabled: boolean, - senderAddress: string, - objectId: string, -) { - return Yup.object({ - to: createSuiAddressValidation(client, suiNSEnabled) - .test( - 'sender-address', - // eslint-disable-next-line no-template-curly-in-string - `NFT is owned by this address`, - (value) => senderAddress !== value, - ) - .test( - 'nft-sender-address', - // eslint-disable-next-line no-template-curly-in-string - `NFT address must be different from receiver address`, - (value) => objectId !== value, - ), - }); -} diff --git a/apps/wallet/src/ui/app/pages/home/nfts/AssetsOptionsMenu.tsx b/apps/wallet/src/ui/app/pages/home/nfts/AssetsOptionsMenu.tsx deleted file mode 100644 index 419b53b6a216e..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nfts/AssetsOptionsMenu.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Menu } from '@headlessui/react'; -import { Ooo24 } from '@mysten/icons'; -import { Link } from 'react-router-dom'; - -const AssetsOptionsMenu = () => { - return ( - - - - - -
    - - {({ active }) => ( - -
    - View Hidden Assets -
    - - )} -
    -
    -
    -
    - ); -}; - -export default AssetsOptionsMenu; diff --git a/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx b/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx deleted file mode 100644 index f61d15c475ece..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import ExplorerLink from '_src/ui/app/components/explorer-link'; -import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; -import { Text } from '_src/ui/app/shared/text'; -import { type SuiObjectData } from '@mysten/sui/client'; -import { formatAddress, parseStructTag } from '@mysten/sui/utils'; - -export default function NonVisualAssets({ items }: { items: SuiObjectData[] }) { - return ( -
    - {items?.length ? ( -
    - {items.map((item) => { - const { address, module, name } = parseStructTag(item.type!); - return ( -
    - - {formatAddress(item.objectId!)} - - -
    - - {`${formatAddress(address)}::${module}::${name}`} - -
    -
    - ); - })} -
    - ) : ( -
    - No Assets found -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx b/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx deleted file mode 100644 index ccc3cba329863..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ErrorBoundary } from '_components/error-boundary'; -import { ampli } from '_src/shared/analytics/ampli'; -import { useBuyNLargeAssets } from '_src/ui/app/components/buynlarge/useBuyNLargeAssets'; -import { NFTDisplayCard } from '_src/ui/app/components/nft-display'; -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { getKioskIdFromOwnerCap, isKioskOwnerToken } from '@mysten/core'; -import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { EyeClose16 } from '@mysten/icons'; -import { type SuiObjectData } from '@mysten/sui/client'; -import { Link } from 'react-router-dom'; - -import { useHiddenAssets } from '../hidden-assets/HiddenAssetsProvider'; - -export default function VisualAssets({ items }: { items: SuiObjectData[] }) { - const { hideAsset } = useHiddenAssets(); - const kioskClient = useKioskClient(); - const bnl = useBuyNLargeAssets(); - - return ( -
    - {items.map((object) => ( - { - ampli.clickedCollectibleCard({ - objectId: object.objectId, - collectibleType: object.type!, - }); - }} - key={object.objectId} - className="no-underline relative" - > -
    -
    - {!isKioskOwnerToken(kioskClient.network, object) && - !bnl.some((item) => item?.objectType === object.type) ? ( -
    -
    - ) : null} -
    - - - -
    - - ))} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/nfts/index.tsx b/apps/wallet/src/ui/app/pages/home/nfts/index.tsx deleted file mode 100644 index 71fa58c939a14..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/nfts/index.tsx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import { useBlockedObjectList } from '_app/hooks/useBlockedObjectList'; -import Alert from '_components/alert'; -import FiltersPortal from '_components/filters-tags'; -import Loading from '_components/loading'; -import LoadingSpinner from '_components/loading/LoadingIndicator'; -import { setToSessionStorage } from '_src/background/storage-utils'; -import { AssetFilterTypes, useGetNFTs } from '_src/ui/app/hooks/useGetNFTs'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import { useOnScreen } from '@mysten/core'; -import { normalizeStructTag } from '@mysten/sui/utils'; -import { useEffect, useMemo, useRef } from 'react'; -import { useParams } from 'react-router-dom'; - -import { useHiddenAssets } from '../hidden-assets/HiddenAssetsProvider'; -import AssetsOptionsMenu from './AssetsOptionsMenu'; -import NonVisualAssets from './NonVisualAssets'; -import VisualAssets from './VisualAssets'; - -function NftsPage() { - const accountAddress = useActiveAddress(); - const { data: blockedObjectList } = useBlockedObjectList(); - const { - data: ownedAssets, - hasNextPage, - isLoading, - isFetchingNextPage, - error, - isPending, - fetchNextPage, - isError, - } = useGetNFTs(accountAddress); - const observerElem = useRef(null); - const { isIntersecting } = useOnScreen(observerElem); - const isSpinnerVisible = isFetchingNextPage && hasNextPage; - - useEffect(() => { - if (isIntersecting && hasNextPage && !isFetchingNextPage) { - fetchNextPage(); - } - }, [isIntersecting, fetchNextPage, hasNextPage, isFetchingNextPage]); - - const handleFilterChange = async (tag: any) => { - await setToSessionStorage('NFTS_PAGE_NAVIGATION', tag.link); - }; - const { filterType } = useParams(); - const filteredNFTs = useMemo(() => { - let filteredData = ownedAssets?.visual; - if (filterType) { - filteredData = ownedAssets?.[filterType as AssetFilterTypes] ?? []; - } - return filteredData?.filter((ownedAsset) => { - if (!ownedAsset.type) { - return true; - } - const normalizedType = normalizeStructTag(ownedAsset.type); - return !blockedObjectList?.includes(normalizedType); - }); - }, [ownedAssets, filterType, blockedObjectList]); - const { hiddenAssetIds } = useHiddenAssets(); - - if (isLoading) { - return ( -
    - -
    - ); - } - - const tags = [ - { name: 'Visual Assets', link: 'nfts' }, - { name: 'Everything Else', link: 'nfts/other' }, - ]; - - return ( -
    - : null} /> - {!!ownedAssets?.other.length && ( - - )} - - {isError ? ( - -
    - Sync error (data might be outdated) -
    - {(error as Error).message} -
    - ) : null} - {filteredNFTs?.length ? ( - filterType === AssetFilterTypes.other ? ( - - ) : ( - - ) - ) : ( -
    - No Assets found -
    - )} -
    -
    - {isSpinnerVisible ? ( -
    - -
    - ) : null} -
    -
    - ); -} - -export default NftsPage; diff --git a/apps/wallet/src/ui/app/pages/home/onramp/icons/Banxa.svg b/apps/wallet/src/ui/app/pages/home/onramp/icons/Banxa.svg deleted file mode 100644 index b7b074824cdd8..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/icons/Banxa.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/wallet/src/ui/app/pages/home/onramp/icons/Coinbase.svg b/apps/wallet/src/ui/app/pages/home/onramp/icons/Coinbase.svg deleted file mode 100644 index 6e96a8631cfed..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/icons/Coinbase.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/wallet/src/ui/app/pages/home/onramp/icons/MoonPay.svg b/apps/wallet/src/ui/app/pages/home/onramp/icons/MoonPay.svg deleted file mode 100644 index 93bada703d21b..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/icons/MoonPay.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/wallet/src/ui/app/pages/home/onramp/icons/Transak.svg b/apps/wallet/src/ui/app/pages/home/onramp/icons/Transak.svg deleted file mode 100644 index 427e2de436450..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/icons/Transak.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/wallet/src/ui/app/pages/home/onramp/index.tsx b/apps/wallet/src/ui/app/pages/home/onramp/index.tsx deleted file mode 100644 index 67dd8bcba2d0f..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ampli } from '_src/shared/analytics/ampli'; -import Alert from '_src/ui/app/components/alert'; -import Overlay from '_src/ui/app/components/overlay'; -import { SectionHeader } from '_src/ui/app/components/SectionHeader'; -import { useActiveAddress } from '_src/ui/app/hooks'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { Heading } from '_src/ui/app/shared/heading'; -import { Text } from '_src/ui/app/shared/text'; -import { useMutation } from '@tanstack/react-query'; -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { useOnrampProviders } from './useOnrampProviders'; - -export function Onramp() { - const navigate = useNavigate(); - const address = useActiveAddress(); - const { providers, setPreferredProvider } = useOnrampProviders(); - - const [preferredProvider, ...otherProviders] = providers ?? []; - - const { mutate, error } = useMutation({ - mutationKey: ['onramp', 'get-provider-url'], - mutationFn: () => { - return preferredProvider.getUrl(address!); - }, - onSuccess: (data) => { - ampli.visitedFiatOnRamp({ providerName: preferredProvider.name }); - window.open(data, '_blank'); - }, - }); - - useEffect(() => { - // This shouldn't happen, but if you land on this page directly and no on-ramps are supported, just bail out - if (providers && providers.length === 0) { - navigate('/tokens'); - } - }, [providers, navigate]); - - const isGuardLoading = useUnlockedGuard(); - - if (!providers || !providers.length || isGuardLoading) return null; - - return ( - { - navigate('/tokens'); - }} - > -
    - {preferredProvider && ( - - Continue checkout out with one of our partners:{' '} - - )} - - - {!!error && ( -
    - An unexpected error occurred. Please try again later. -
    - )} - -
    - {otherProviders.map((provider) => { - return ( - - ); - })} -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/onramp/types.ts b/apps/wallet/src/ui/app/pages/home/onramp/types.ts deleted file mode 100644 index 46c3c2ddbfbd6..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type ComponentProps, type FC } from 'react'; - -export interface OnrampProvider { - key: string; - icon: FC>; - name: string; - checkSupported(): Promise; - getUrl(address: string): Promise; -} diff --git a/apps/wallet/src/ui/app/pages/home/onramp/useOnrampProviders.ts b/apps/wallet/src/ui/app/pages/home/onramp/useOnrampProviders.ts deleted file mode 100644 index fce1a2b25be07..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/onramp/useOnrampProviders.ts +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { growthbook } from '_src/ui/app/experimentation/feature-gating'; -import { useFeatureIsOn } from '@growthbook/growthbook-react'; -import { useQuery } from '@tanstack/react-query'; -import { useState } from 'react'; - -import Banxa from './icons/Banxa.svg'; -import MoonPay from './icons/MoonPay.svg'; -import Transak from './icons/Transak.svg'; -import { type OnrampProvider } from './types'; - -const TRANSAK_API_KEY = - process.env.NODE_ENV === 'production' - ? '0318063c-0380-4e20-9c73-e08836240c17' - : 'c72e867b-4069-4e22-a01e-4553353faefd'; - -const MOONPAY_API_KEY = - process.env.NODE_ENV === 'production' - ? 'pk_live_iL2LFRM1wCc4EfBuxFJSVTkI8Xno4a' - : 'pk_test_RwNag1qi8jFoymVchhCSc5cYnqyPrVd5'; - -const BACKEND_HOST = - process.env.NODE_ENV === 'production' ? 'https://apps-backend.sui.io' : 'http://localhost:3003'; - -const ONRAMP_PROVIDER: OnrampProvider[] = [ - { - key: 'banxa', - name: 'Banxa', - icon: Banxa, - checkSupported: async () => { - const isOn = await growthbook.getFeatureValue('wallet-onramp-banxa', false); - return isOn; - }, - getUrl: async (address) => { - const params = new URLSearchParams({ - coinType: 'SUI', - fiatType: 'USD', - fiatAmount: '100', - blockchain: 'SUI', - theme: 'dark', - walletAddress: address, - returnUrl: window.location.href, - }); - const url = `https://suiwallet.banxa.com/?${params}`; - return url; - }, - }, - { - key: 'transak', - icon: Transak, - name: 'Transak', - checkSupported: async () => { - const isOn = await growthbook.getFeatureValue('wallet-onramp-transak', false); - return isOn; - }, - getUrl: async (address) => { - const params = new URLSearchParams({ - apiKey: TRANSAK_API_KEY, - environment: process.env.NODE_ENV === 'production' ? 'PRODUCTION' : 'STAGING', - // If you want to test ETH values, you can use something like this: - // cryptoCurrencyCode: 'ETH', - // walletAddress: '0x000000000000000000000000000000000000dead', - cryptoCurrencyCode: 'SUI', - walletAddress: address, - disableWalletAddressForm: 'true', - themeColor: '#6fbcf0', - }); - - return process.env.NODE_ENV === 'production' - ? `https://global.transak.com?${params}` - : `https://global-stg.transak.com?${params}`; - }, - }, - { - key: 'moonpay', - icon: MoonPay, - name: 'MoonPay', - checkSupported: async () => { - const isOn = await growthbook.getFeatureValue('wallet-onramp-moonpay', false); - if (!isOn) return false; - try { - const res = await fetch(`https://api.moonpay.com/v4/ip_address?apiKey=${MOONPAY_API_KEY}`); - const data = (await res.json()) as { - isAllowed: boolean; - isBuyAllowed: boolean; - isSellAllowed: boolean; - }; - - return data.isAllowed && data.isBuyAllowed; - } catch { - return false; - } - }, - getUrl: async (address) => { - const params = new URLSearchParams({ - theme: 'light', - colorCode: '#6fbcf0', - currencyCode: 'SUI', - walletAddress: address, - environment: process.env.NODE_ENV === 'production' ? 'PRODUCTION' : 'STAGING', - }); - - const res = await fetch(`${BACKEND_HOST}/moonpay-url?${params}`); - - const data = (await res.json()) as { url: string }; - - return data.url; - }, - }, -]; - -const PREFERRED_ONRAMP_PROVIDER_KEY = 'preferred-onramp-provider'; - -export function useOnrampProviders() { - const onrampEnabled = useFeatureIsOn('wallet-onramp'); - const [preferredProviderKey, setPreferredProviderKey] = useState(() => - localStorage.getItem(PREFERRED_ONRAMP_PROVIDER_KEY), - ); - - const { data } = useQuery({ - queryKey: ['onramp', 'get-providers'], - queryFn: async () => { - const supportedProviders = await Promise.all( - ONRAMP_PROVIDER.map(async (provider) => { - const supported = await provider.checkSupported(); - return supported ? provider.key : null; - }), - ); - - // NOTE: We don't put the actual provider instances into the cache, because that will fail when persisting. - // Instead, we use a selector to get the actual provider instances from the keys. - return supportedProviders.filter(Boolean) as string[]; - }, - enabled: onrampEnabled, - select(providerKeys) { - const providers = providerKeys - .map((key) => ONRAMP_PROVIDER.find((provider) => provider.key === key)) - .filter(Boolean) as OnrampProvider[]; - - if (!preferredProviderKey) { - return providers; - } - - const preferredProvider = providers.find(({ key }) => key === preferredProviderKey); - const nonPreferredProviders = providers.filter(({ key }) => key !== preferredProviderKey); - - return [preferredProvider, ...nonPreferredProviders].filter(Boolean) as OnrampProvider[]; - }, - }); - - return { - providers: data, - setPreferredProvider(key: string) { - localStorage.setItem(PREFERRED_ONRAMP_PROVIDER_KEY, key); - setPreferredProviderKey(key); - }, - }; -} diff --git a/apps/wallet/src/ui/app/pages/home/receipt/index.tsx b/apps/wallet/src/ui/app/pages/home/receipt/index.tsx deleted file mode 100644 index 1355252e3f404..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/receipt/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Alert from '_components/alert'; -import Loading from '_components/loading'; -import Overlay from '_components/overlay'; -import { ReceiptCard } from '_src/ui/app/components/receipt-card'; -import { useActiveAddress } from '_src/ui/app/hooks/useActiveAddress'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { Check32 } from '@mysten/icons'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { useQuery } from '@tanstack/react-query'; -import { useCallback, useMemo, useState } from 'react'; -import { Navigate, useLocation, useNavigate, useSearchParams } from 'react-router-dom'; - -function ReceiptPage() { - const location = useLocation(); - const [searchParams] = useSearchParams(); - const [showModal, setShowModal] = useState(true); - const activeAddress = useActiveAddress(); - - // get tx results from url params - const transactionId = searchParams.get('txdigest'); - const fromParam = searchParams.get('from'); - const client = useSuiClient(); - - const { data, isPending, isError } = useQuery({ - queryKey: ['transactions-by-id', transactionId], - queryFn: async () => { - return client.getTransactionBlock({ - digest: transactionId!, - options: { - showBalanceChanges: true, - showObjectChanges: true, - showInput: true, - showEffects: true, - showEvents: true, - }, - }); - }, - enabled: !!transactionId, - retry: 8, - initialData: location.state?.response, - }); - - const navigate = useNavigate(); - // return to previous route or from param if available - const closeReceipt = useCallback(() => { - fromParam ? navigate(`/${fromParam}`) : navigate(-1); - }, [fromParam, navigate]); - - const pageTitle = useMemo(() => { - if (data) { - const executionStatus = data.effects?.status.status; - - // TODO: Infer out better name: - const transferName = 'Transaction'; - - return `${executionStatus === 'success' ? transferName : 'Transaction Failed'}`; - } - - return 'Transaction Failed'; - }, [/*activeAddress,*/ data]); - - const isGuardLoading = useUnlockedGuard(); - - if (!transactionId || !activeAddress) { - return ; - } - - return ( - - } - > - {isError ? ( -
    - Something went wrong -
    - ) : null} - - {data && } -
    -
    - ); -} - -export default ReceiptPage; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/PortfolioName.tsx b/apps/wallet/src/ui/app/pages/home/tokens/PortfolioName.tsx deleted file mode 100644 index 768c2afd2062d..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/PortfolioName.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; - -export function PortfolioName({ name }: { name: string }) { - return ( -
    -
    -
    - - {name} Portfolio - -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenDetailsPage.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenDetailsPage.tsx deleted file mode 100644 index 22e713efa7412..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenDetailsPage.tsx +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import TokenDetails from './TokensDetails'; - -function TokenDetailsPage() { - return ; -} - -export default TokenDetailsPage; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx deleted file mode 100644 index 5195507018769..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { LargeButton } from '_app/shared/LargeButton'; -import { ampli } from '_src/shared/analytics/ampli'; -import { - DELEGATED_STAKES_QUERY_REFETCH_INTERVAL, - DELEGATED_STAKES_QUERY_STALE_TIME, -} from '_src/shared/constants'; -import { Text } from '_src/ui/app/shared/text'; -import { useFormatCoin, useGetDelegatedStake } from '@mysten/core'; -import { WalletActionStake24 } from '@mysten/icons'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -export function TokenIconLink({ - accountAddress, - disabled, -}: { - accountAddress: string; - disabled: boolean; -}) { - const { data: delegatedStake, isPending } = useGetDelegatedStake({ - address: accountAddress, - staleTime: DELEGATED_STAKES_QUERY_STALE_TIME, - refetchInterval: DELEGATED_STAKES_QUERY_REFETCH_INTERVAL, - }); - - // Total active stake for all delegations - const totalActivePendingStake = useMemo(() => { - if (!delegatedStake) return 0n; - return delegatedStake.reduce( - (acc, curr) => curr.stakes.reduce((total, { principal }) => total + BigInt(principal), acc), - 0n, - ); - }, [delegatedStake]); - - const [formatted, symbol, queryResult] = useFormatCoin(totalActivePendingStake, SUI_TYPE_ARG); - - return ( - { - ampli.clickedStakeSui({ - isCurrentlyStaking: totalActivePendingStake > 0, - sourceFlow: 'Home page', - }); - }} - loading={isPending || queryResult.isPending} - before={} - data-testid={`stake-button-${formatted}-${symbol}`} - > -
    - - {totalActivePendingStake ? 'Currently Staked' : 'Stake and Earn SUI'} - - - {!!totalActivePendingStake && ( - - {formatted} {symbol} - - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx deleted file mode 100644 index 2ef4071bd1158..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { CoinItem } from '_components/active-coins-card/CoinItem'; -import { ampli } from '_src/shared/analytics/ampli'; -import { type CoinBalance } from '@mysten/sui/client'; -import { MIST_PER_SUI } from '@mysten/sui/utils'; -import { type ReactNode } from 'react'; -import { Link } from 'react-router-dom'; - -type Props = { - coinBalance: CoinBalance; - centerAction?: ReactNode; - subtitle?: string; -}; - -export function TokenLink({ coinBalance, centerAction, subtitle }: Props) { - return ( - - ampli.selectedCoin({ - coinType: coinBalance.coinType, - totalBalance: Number(BigInt(coinBalance.totalBalance) / MIST_PER_SUI), - sourceFlow: 'TokenLink', - }) - } - key={coinBalance.coinType} - className="no-underline w-full group/coin" - > - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenList.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenList.tsx deleted file mode 100644 index c888cefb00b6c..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenList.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Collapsible } from '_src/ui/app/shared/collapse'; -import { type ReactNode } from 'react'; - -type Props = { - title: string; - defaultOpen?: boolean; - children: ReactNode; -}; - -export function TokenList({ title, defaultOpen, children }: Props) { - return ( -
    - - {children} - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx deleted file mode 100644 index 19296c0687f89..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx +++ /dev/null @@ -1,552 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; -import { useIsWalletDefiEnabled } from '_app/hooks/useIsWalletDefiEnabled'; -import { LargeButton } from '_app/shared/LargeButton'; -import { Text } from '_app/shared/text'; -import { ButtonOrLink } from '_app/shared/utils/ButtonOrLink'; -import Alert from '_components/alert'; -import { CoinIcon } from '_components/coin-icon'; -import Loading from '_components/loading'; -import { filterAndSortTokenBalances } from '_helpers'; -import { useAppSelector, useCoinsReFetchingConfig, useSortedCoinsByCategories } from '_hooks'; -import { UsdcPromoBanner } from '_pages/home/usdc-promo/UsdcPromoBanner'; -import { - DELEGATED_STAKES_QUERY_REFETCH_INTERVAL, - DELEGATED_STAKES_QUERY_STALE_TIME, -} from '_shared/constants'; -import { ampli } from '_src/shared/analytics/ampli'; -import { API_ENV } from '_src/shared/api-env'; -import { FEATURES } from '_src/shared/experimentation/features'; -import { AccountsList } from '_src/ui/app/components/accounts/AccountsList'; -import { UnlockAccountButton } from '_src/ui/app/components/accounts/UnlockAccountButton'; -import { BuyNLargeHomePanel } from '_src/ui/app/components/buynlarge/HomePanel'; -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useCoinMetadataOverrides } from '_src/ui/app/hooks/useCoinMetadataOverride'; -import { usePinnedCoinTypes } from '_src/ui/app/hooks/usePinnedCoinTypes'; -import FaucetRequestButton from '_src/ui/app/shared/faucet/FaucetRequestButton'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import { useFeature } from '@growthbook/growthbook-react'; -import { - useAppsBackend, - useBalanceInUSD, - useCoinMetadata, - useFormatCoin, - useGetDelegatedStake, -} from '@mysten/core'; -import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { Info12, Pin16, Unpin16 } from '@mysten/icons'; -import { type CoinBalance as CoinBalanceType } from '@mysten/sui/client'; -import { formatAddress, parseStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; -import clsx from 'clsx'; -import { useEffect, useState, type ReactNode } from 'react'; - -import Interstitial, { type InterstitialConfig } from '../interstitial'; -import { useOnrampProviders } from '../onramp/useOnrampProviders'; -import { CoinBalance } from './coin-balance'; -import { PortfolioName } from './PortfolioName'; -import { TokenIconLink } from './TokenIconLink'; -import { TokenLink } from './TokenLink'; -import { TokenList } from './TokenList'; - -type TokenDetailsProps = { - coinType?: string; -}; - -function PinButton({ unpin, onClick }: { unpin?: boolean; onClick: () => void }) { - return ( - - ); -} - -function TokenRowButton({ - coinBalance, - children, - to, - onClick, -}: { - coinBalance: CoinBalanceType; - children: ReactNode; - to: string; - onClick?: () => void; -}) { - return ( - - {children} - - ); -} - -export function TokenRow({ - coinBalance, - renderActions, - onClick, -}: { - coinBalance: CoinBalanceType; - renderActions?: boolean; - onClick?: () => void; -}) { - const coinType = coinBalance.coinType; - const balance = BigInt(coinBalance.totalBalance); - const [formatted, symbol, { data: coinMeta }] = useFormatCoin(balance, coinType); - const Tag = onClick ? 'button' : 'div'; - const params = new URLSearchParams({ - type: coinBalance.coinType, - }); - - const balanceInUsd = useBalanceInUSD(coinBalance.coinType, coinBalance.totalBalance); - - const coinMetadataOverrides = useCoinMetadataOverrides(); - return ( - -
    - -
    - - {coinMetadataOverrides[coinBalance.coinType]?.name || coinMeta?.name || symbol} - - - {renderActions && ( -
    - - {symbol} - -
    - )} - - {renderActions ? ( -
    - - ampli.selectedCoin({ - coinType: coinBalance.coinType, - totalBalance: Number(formatted), - sourceFlow: 'TokenDetails', - }) - } - > - Send - - { - ampli.clickedSwapCoin({ - coinType: coinBalance.coinType, - totalBalance: Number(formatted), - sourceFlow: 'TokenRow', - }); - }} - > - Swap - -
    - ) : ( -
    - - {symbol} - - - {formatAddress(coinType)} - -
    - )} -
    -
    - -
    - {balance > 0n && ( - - {formatted} {symbol} - - )} - - {balanceInUsd && balanceInUsd > 0 ? ( - - {Number(balanceInUsd).toLocaleString('en', { - style: 'currency', - currency: 'USD', - })} - - ) : null} -
    -
    - ); -} - -export function MyTokens({ - coinBalances, - isLoading, - isFetched, -}: { - coinBalances: CoinBalanceType[]; - isLoading: boolean; - isFetched: boolean; -}) { - const isDefiWalletEnabled = useIsWalletDefiEnabled(); - const apiEnv = useAppSelector(({ app }) => app.apiEnv); - - const [_, { pinCoinType, unpinCoinType }] = usePinnedCoinTypes(); - - const { recognized, pinned, unrecognized } = useSortedCoinsByCategories(coinBalances); - - // Avoid perpetual loading state when fetching and retry keeps failing; add isFetched check. - const isFirstTimeLoading = isLoading && !isFetched; - - return ( - - {recognized.length > 0 && ( - - {recognized.map((coinBalance) => - isDefiWalletEnabled ? ( - - ) : ( - - ), - )} - - )} - - {pinned.length > 0 && ( - - {pinned.map((coinBalance) => ( - { - ampli.unpinnedCoin({ coinType: coinBalance.coinType }); - unpinCoinType(coinBalance.coinType); - }} - /> - } - /> - ))} - - )} - - {unrecognized.length > 0 && ( - - {unrecognized.map((coinBalance) => ( - { - ampli.pinnedCoin({ coinType: coinBalance.coinType }); - pinCoinType(coinBalance.coinType); - }} - /> - } - /> - ))} - - )} - - ); -} - -function getMostNestedName(parsed: ReturnType) { - if (parsed.typeParams.length === 0) { - return parsed.name; - } - - if (typeof parsed.typeParams[0] === 'string') { - return parsed.typeParams[0]; - } - - return getMostNestedName(parsed.typeParams[0]); -} - -function getFallbackSymbol(coinType: string) { - const parsed = parseStructTag(coinType); - return getMostNestedName(parsed); -} - -function TokenDetails({ coinType }: TokenDetailsProps) { - const isDefiWalletEnabled = useIsWalletDefiEnabled(); - const [interstitialDismissed, setInterstitialDismissed] = useState(false); - const activeCoinType = coinType || SUI_TYPE_ARG; - const activeAccount = useActiveAccount(); - const activeAccountAddress = activeAccount?.address; - const domainName = useResolveSuiNSName(activeAccountAddress); - - const { staleTime, refetchInterval } = useCoinsReFetchingConfig(); - const { - data: coinBalance, - isError, - isPending, - isFetched, - } = useSuiClientQuery( - 'getBalance', - { coinType: activeCoinType, owner: activeAccountAddress! }, - { enabled: !!activeAccountAddress, refetchInterval, staleTime }, - ); - - const { apiEnv } = useAppSelector((state) => state.app); - const isMainnet = apiEnv === API_ENV.mainnet; - const { request } = useAppsBackend(); - const { data } = useQuery({ - queryKey: ['apps-backend', 'monitor-network'], - queryFn: () => - request<{ degraded: boolean }>('monitor-network', { - project: 'WALLET', - }), - // Keep cached for 2 minutes: - staleTime: 2 * 60 * 1000, - retry: false, - enabled: isMainnet, - }); - - const { - data: coinBalances, - isPending: coinBalancesLoading, - isFetched: coinBalancesFetched, - } = useSuiClientQuery( - 'getAllBalances', - { owner: activeAccountAddress! }, - { - enabled: !!activeAccountAddress, - staleTime, - refetchInterval, - select: filterAndSortTokenBalances, - }, - ); - - const { data: delegatedStake } = useGetDelegatedStake({ - address: activeAccountAddress || '', - staleTime: DELEGATED_STAKES_QUERY_STALE_TIME, - refetchInterval: DELEGATED_STAKES_QUERY_REFETCH_INTERVAL, - }); - - const walletInterstitialConfig = useFeature( - FEATURES.WALLET_INTERSTITIAL_CONFIG, - ).value; - - const { providers } = useOnrampProviders(); - - const tokenBalance = BigInt(coinBalance?.totalBalance ?? 0); - const [formatted] = useFormatCoin(tokenBalance, activeCoinType); - - const { data: coinMetadata } = useCoinMetadata(activeCoinType); - const coinSymbol = coinMetadata ? coinMetadata.symbol : getFallbackSymbol(activeCoinType); - - // Avoid perpetual loading state when fetching and retry keeps failing add isFetched check - const isFirstTimeLoading = isPending && !isFetched; - - useEffect(() => { - const dismissed = - walletInterstitialConfig?.dismissKey && - localStorage.getItem(walletInterstitialConfig.dismissKey); - setInterstitialDismissed(dismissed === 'true'); - }, [walletInterstitialConfig?.dismissKey]); - - if ( - navigator.userAgent !== 'Playwright' && - walletInterstitialConfig?.enabled && - !interstitialDismissed - ) { - return ( - { - setInterstitialDismissed(true); - }} - /> - ); - } - const accountHasSui = coinBalances?.some(({ coinType }) => coinType === SUI_TYPE_ARG); - - if (!activeAccountAddress) { - return null; - } - return ( - <> - {isMainnet && data?.degraded && ( -
    - -
    - - We're sorry that the app is running slower than usual. We're working to fix the issue - and appreciate your patience. - -
    -
    - )} - - - {coinType && } - -
    - - - - -
    - - {activeAccount.isLocked ? null : ( - <> -
    -
    - -
    - - {!accountHasSui ? ( -
    -
    - - {isMainnet - ? 'Buy SUI to get started' - : 'To send transactions on the Sui network, you need SUI in your wallet.'} - -
    - -
    - ) : null} - {isError ? ( - -
    - Error updating balance -
    -
    - ) : null} -
    - {isMainnet ? ( - - Buy - - ) : null} - - - Send - - - { - if (!coinBalance) { - return; - } - - ampli.clickedSwapCoin({ - coinType: coinBalance.coinType, - totalBalance: Number(formatted), - sourceFlow: 'LargeButton-TokenDetails', - }); - }} - > - Swap - - {!accountHasSui && ( - - Stake - - )} -
    - -
    - {accountHasSui || delegatedStake?.length ? ( - - ) : null} -
    -
    - - )} -
    - {activeAccount.isLocked ? ( - - ) : ( - - )} -
    -
    - - ); -} - -export default TokenDetails; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokensStackIcon.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokensStackIcon.tsx deleted file mode 100644 index 45f2d593d5a8a..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokensStackIcon.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { type SVGProps } from 'react'; - -export const SvgSuiTokensStack = (props: SVGProps) => ( - - - - - - - - - - - - - - -); -export default SvgSuiTokensStack; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/CoinBalance.module.scss b/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/CoinBalance.module.scss deleted file mode 100644 index 996412dc5a3ca..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/CoinBalance.module.scss +++ /dev/null @@ -1,119 +0,0 @@ -@use '_utils'; -@use '_values/colors'; - -.container { - display: flex; - flex-flow: row nowrap; - align-items: center; - gap: 10px; - - &.row-item { - padding: 15px 0; - - & + & { - border-top: 1px solid colors.$gray-45; - } - } -} - -.coin-balance-btn { - cursor: pointer; -} - -.coin-icon { - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - width: 30px; - height: 30px; - border-radius: 50%; - color: colors.$white; - background-color: colors.$gray-75; - flex-shrink: 0; - - &.sui { - background-color: colors.$sui-blue; - } -} - -.coin-name-container { - display: flex; - flex-flow: column nowrap; - gap: 6px; - flex: 1; - overflow: hidden; -} - -.coin-name { - color: colors.$gray-90; - text-transform: capitalize; - - @include utils.typography('Primary/Body-SB'); - @include utils.overflow-ellipsis; -} - -.coin-symbol { - color: colors.$gray-65; - text-transform: uppercase; - - @include utils.typography('Primary/BodySmall-M'); - @include utils.overflow-ellipsis; -} - -.value-container { - display: flex; - flex-flow: row nowrap; - flex: 1; - overflow: hidden; - - &.row-item { - flex: 1; - justify-content: flex-end; - } - - &.standalone { - align-items: baseline; - } -} - -.value { - &.standalone { - color: colors.$gray-100; - - @include utils.typography('Primary/Heading1-B'); - } - - &.row-item { - flex-shrink: 0; - - @include utils.overflow-ellipsis; - } -} - -.symbol { - &.standalone { - margin-left: 6px; - color: colors.$gray-65; - - @include utils.typography('Primary/Heading3-M'); - } - - &.row-item { - flex-shrink: 1; - - @include utils.overflow-ellipsis; - } -} - -.value, -.symbol { - white-space: nowrap; - - &.row-item { - color: colors.$gray-90; - margin-right: 4px; - - @include utils.typography('Primary/Body-M'); - } -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx b/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx deleted file mode 100644 index 84086917249f5..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useIsWalletDefiEnabled } from '_app/hooks/useIsWalletDefiEnabled'; -import { useAppSelector } from '_hooks'; -import { API_ENV } from '_shared/api-env'; -import { Heading } from '_src/ui/app/shared/heading'; -import { Text } from '_src/ui/app/shared/text'; -import { useBalanceInUSD, useFormatCoin } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -export type CoinProps = { - type: string; - amount: bigint; -}; - -function WalletBalanceUsd({ amount: walletBalance }: { amount: bigint }) { - const isDefiWalletEnabled = useIsWalletDefiEnabled(); - const formattedWalletBalance = useBalanceInUSD(SUI_TYPE_ARG, walletBalance); - - const walletBalanceInUsd = useMemo(() => { - if (!formattedWalletBalance) return null; - - return `~${formattedWalletBalance.toLocaleString('en', { - style: 'currency', - currency: 'USD', - })} USD`; - }, [formattedWalletBalance]); - - if (!walletBalanceInUsd) { - return null; - } - - return ( - - {walletBalanceInUsd} - - ); -} - -export function CoinBalance({ amount: walletBalance, type }: CoinProps) { - const { apiEnv } = useAppSelector((state) => state.app); - const [formatted, symbol] = useFormatCoin(walletBalance, type); - - return ( -
    -
    - - {formatted} - - - - {symbol} - -
    -
    {apiEnv === API_ENV.mainnet ? : null}
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/icon-link/IconLink.module.scss b/apps/wallet/src/ui/app/pages/home/tokens/icon-link/IconLink.module.scss deleted file mode 100644 index 1dcb43d8fc21e..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/icon-link/IconLink.module.scss +++ /dev/null @@ -1,66 +0,0 @@ -@use '_values/colors'; -@use 'sass:color'; -@use '_utils'; - -.container { - display: flex; - flex-flow: column nowrap; - align-items: center; - background-color: color.adjust(colors.$sui-blue, $alpha: -0.9); - border-radius: 15px; - padding: 10px 14px; - text-decoration: none; - color: colors.$cta-blue; - flex-basis: 98px; - - i { - font-size: 18px; - font-weight: 400; - } - - &:nth-child(2) { - i { - display: flex; - position: relative; - align-items: center; - justify-content: center; - - @include utils.angled-arrow; - - font-size: 18px; - font-weight: 400; - margin: auto; - color: colors.$cta-blue; - } - } - - &:hover { - color: colors.$cta-blue-hover; - } - - &.disabled { - pointer-events: none; - background-color: colors.$gray-40; - color: colors.$gray-60; - - i { - color: colors.$gray-60; - } - } -} - -.icon-container { - display: flex; - flex-flow: column nowrap; - align-items: center; - justify-content: center; - color: colors.$cta-blue; - padding: 5px; - font-size: 16px; -} - -.text { - text-align: center; - font-weight: 600; - font-size: 13px; -} diff --git a/apps/wallet/src/ui/app/pages/home/tokens/icon-link/index.tsx b/apps/wallet/src/ui/app/pages/home/tokens/icon-link/index.tsx deleted file mode 100644 index 82040af93a815..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/icon-link/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { Text } from '_app/shared/text'; -import cl from 'clsx'; -import { memo } from 'react'; -import type { ReactNode } from 'react'; -import { Link } from 'react-router-dom'; - -import st from './IconLink.module.scss'; - -export type IconLinkProps = { - to: string; - icon: ReactNode; - disabled?: boolean; - text: string; -}; - -function IconLink({ to, icon, disabled = false, text }: IconLinkProps) { - return ( - -
    {icon}
    - - {text} - - - ); -} - -export default memo(IconLink); diff --git a/apps/wallet/src/ui/app/pages/home/tokens/index.tsx b/apps/wallet/src/ui/app/pages/home/tokens/index.tsx deleted file mode 100644 index d6c4d9fdd6c82..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/tokens/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Route, Routes } from 'react-router-dom'; - -import TokenDetailsPage from './TokenDetailsPage'; -import TokenDetails from './TokensDetails'; - -function TokensPage() { - return ( - - } /> - } /> - - ); -} - -export default TokensPage; diff --git a/apps/wallet/src/ui/app/pages/home/transactions/CompletedTransactions.tsx b/apps/wallet/src/ui/app/pages/home/transactions/CompletedTransactions.tsx deleted file mode 100644 index 8e9f8707bd747..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transactions/CompletedTransactions.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Alert from '_components/alert'; -import { ErrorBoundary } from '_components/error-boundary'; -import Loading from '_components/loading'; -import { TransactionCard } from '_components/transactions-card'; -import { NoActivityCard } from '_components/transactions-card/NoActivityCard'; -import { useQueryTransactionsByAddress } from '_hooks'; -import { useActiveAddress } from '_src/ui/app/hooks/useActiveAddress'; - -export function CompletedTransactions() { - const activeAddress = useActiveAddress(); - const { data: txns, isPending, error } = useQueryTransactionsByAddress(activeAddress); - if (error) { - return {(error as Error)?.message}; - } - return ( - - {txns?.length && activeAddress ? ( - txns.map((txn) => ( - - - - )) - ) : ( - - )} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/transactions/QredoPendingTransactions.tsx b/apps/wallet/src/ui/app/pages/home/transactions/QredoPendingTransactions.tsx deleted file mode 100644 index c4c099acb4121..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transactions/QredoPendingTransactions.tsx +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ErrorBoundary } from '_components/error-boundary'; -import Loading from '_components/loading'; -import { NoActivityCard } from '_components/transactions-card/NoActivityCard'; -import { isQredoAccountSerializedUI } from '_src/background/accounts/QredoAccount'; -import { type TransactionStatus } from '_src/shared/qredo-api'; -import Alert from '_src/ui/app/components/alert'; -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useGetQredoTransactions } from '_src/ui/app/hooks/useGetQredoTransactions'; - -import { QredoTransaction } from './QredoTransaction'; - -const PENDING_QREDO_TRANSACTION_STATUSES: TransactionStatus[] = [ - 'approved', - 'authorized', - 'created', - 'pending', - 'pushed', - 'scheduled', - 'signed', -]; - -export function QredoPendingTransactions() { - const activeAccount = useActiveAccount(); - const activeAddress = activeAccount?.address; - const isQredoAccount = !!(activeAccount && isQredoAccountSerializedUI(activeAccount)); - const qredoID = isQredoAccount ? activeAccount.sourceID : undefined; - const { - data: qredoTransactions, - isPending, - error, - } = useGetQredoTransactions({ - qredoID, - filterStatus: PENDING_QREDO_TRANSACTION_STATUSES, - }); - if (error) { - return {(error as Error)?.message}; - } - return ( - - {qredoTransactions?.length && activeAddress ? ( - qredoTransactions.map((txn) => ( - - - - )) - ) : ( - - )} - - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx b/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx deleted file mode 100644 index c82e076cf92e2..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { toUtf8OrB64 } from '_src/shared/utils'; -import LoadingIndicator from '_src/ui/app/components/loading/LoadingIndicator'; -import { TxnIcon } from '_src/ui/app/components/transactions-card/TxnIcon'; -import { useGetQredoTransaction } from '_src/ui/app/hooks/useGetQredoTransaction'; -import { Text } from '_src/ui/app/shared/text'; -import { formatDate, useOnScreen } from '@mysten/core'; -import { bcs } from '@mysten/sui/bcs'; -import { fromBase64 } from '@mysten/sui/utils'; -import { useMemo, useRef } from 'react'; - -export type QredoTransactionProps = { - qredoID?: string; - qredoTransactionID?: string; -}; - -export function QredoTransaction({ qredoID, qredoTransactionID }: QredoTransactionProps) { - const transactionElementRef = useRef(null); - const { isIntersecting } = useOnScreen(transactionElementRef); - const { data, isPending, error } = useGetQredoTransaction({ - qredoID, - qredoTransactionID, - forceDisabled: !isIntersecting, - }); - const messageWithIntent = useMemo(() => { - if (data?.MessageWithIntent) { - return fromBase64(data.MessageWithIntent); - } - return null; - }, [data?.MessageWithIntent]); - - const isSignMessage = messageWithIntent - ? bcs.IntentScope.parse(messageWithIntent).PersonalMessage - : false; - - const transactionBytes = useMemo(() => messageWithIntent?.slice(3) || null, [messageWithIntent]); - const messageToSign = - useMemo( - () => transactionBytes && toUtf8OrB64(transactionBytes), - [transactionBytes], - )?.message?.slice(0, 300) || null; - return ( -
    -
    - -
    -
    - {isPending ? ( - <> -
    -
    - - ) : data ? ( - <> -
    - - {isSignMessage ? 'Sign personal message' : 'Transaction'} - - - ({data.status}) - -
    - - #{data.txID} - - {isSignMessage && messageToSign ? ( -
    - - {messageToSign} - -
    - ) : null} - {data.timestamps.created ? ( - - {formatDate(data.timestamps.created * 1000, ['month', 'day', 'hour', 'minute'])} - - ) : null} -
    - - Check status in Qredo app - - -
    - - ) : ( - - {(error as Error)?.message || 'Something went wrong while fetching transaction details'} - - )} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/transactions/index.tsx b/apps/wallet/src/ui/app/pages/home/transactions/index.tsx deleted file mode 100644 index 5c81df70e48cd..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transactions/index.tsx +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import FiltersPortal from '_components/filters-tags'; -import { isQredoAccountSerializedUI } from '_src/background/accounts/QredoAccount'; -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import PageTitle from '_src/ui/app/shared/PageTitle'; -import cl from 'clsx'; -import { Navigate, useParams } from 'react-router-dom'; - -import { CompletedTransactions } from './CompletedTransactions'; -import { QredoPendingTransactions } from './QredoPendingTransactions'; - -function TransactionBlocksPage() { - const activeAccount = useActiveAccount(); - const isQredoAccount = !!(activeAccount && isQredoAccountSerializedUI(activeAccount)); - const { status } = useParams(); - const isPendingTransactions = status === 'pending'; - if (useUnlockedGuard()) { - return null; - } - if (activeAccount && !isQredoAccount && isPendingTransactions) { - return ; - } - return ( -
    - {isQredoAccount ? ( - - ) : null} - -
    - {isPendingTransactions ? : } -
    -
    - ); -} - -export default TransactionBlocksPage; diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx deleted file mode 100644 index a3ab73764b3a8..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ActiveCoinsCard } from '_components/active-coins-card'; -import Overlay from '_components/overlay'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useNavigate, useSearchParams } from 'react-router-dom'; - -function CoinsSelectorPage() { - const [searchParams] = useSearchParams(); - const coinType = searchParams.get('type') || SUI_TYPE_ARG; - const navigate = useNavigate(); - - if (useUnlockedGuard()) { - return null; - } - - return ( - - navigate( - `/send?${new URLSearchParams({ - type: coinType, - }).toString()}`, - ) - } - > - - - ); -} - -export default CoinsSelectorPage; diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx deleted file mode 100644 index 37038c6a2517d..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/PreviewTransfer.tsx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { TxnAddress } from '_components/receipt-card/TxnAddress'; -import { TxnAmount } from '_components/receipt-card/TxnAmount'; -import { parseAmount } from '_helpers'; -import { useActiveAddress } from '_src/ui/app/hooks/useActiveAddress'; -import { GAS_SYMBOL } from '_src/ui/app/redux/slices/sui-objects/Coin'; -import { useCoinMetadata } from '@mysten/core'; - -export type PreviewTransferProps = { - coinType: string; - to: string; - amount: string; - approximation?: boolean; - gasBudget?: string; -}; - -export function PreviewTransfer({ - coinType, - to, - amount, - approximation, - gasBudget, -}: PreviewTransferProps) { - const accountAddress = useActiveAddress(); - const { data: metadata } = useCoinMetadata(coinType); - const amountWithoutDecimals = parseAmount(amount, metadata?.decimals ?? 0); - - return ( -
    - - - -
    -
    - - Estimated Gas Fees - -
    - - {gasBudget} {GAS_SYMBOL} - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx deleted file mode 100644 index e523c451770b5..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useActiveAddress } from '_app/hooks/useActiveAddress'; -import BottomMenuLayout, { Content, Menu } from '_app/shared/bottom-menu-layout'; -import { Button } from '_app/shared/ButtonUI'; -import { Text } from '_app/shared/text'; -import { AddressInput } from '_components/address-input'; -import Alert from '_components/alert'; -import Loading from '_components/loading'; -import { parseAmount } from '_helpers'; -import { useGetAllCoins } from '_hooks'; -import { GAS_SYMBOL } from '_src/ui/app/redux/slices/sui-objects/Coin'; -import { InputWithAction } from '_src/ui/app/shared/InputWithAction'; -import { CoinFormat, useCoinMetadata, useFormatCoin, useSuiNSEnabled } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { ArrowRight16 } from '@mysten/icons'; -import { type CoinStruct } from '@mysten/sui/client'; -import { isValidSuiNSName, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useQuery } from '@tanstack/react-query'; -import { Field, Form, Formik, useFormikContext } from 'formik'; -import { useEffect, useMemo } from 'react'; - -import { createTokenTransferTransaction } from './utils/transaction'; -import { createValidationSchemaStepOne } from './validation'; - -const initialValues = { - to: '', - amount: '', - isPayAllSui: false, - gasBudgetEst: '', -}; - -export type FormValues = typeof initialValues; - -export type SubmitProps = { - to: string; - amount: string; - isPayAllSui: boolean; - coinIds: string[]; - coins: CoinStruct[]; - gasBudgetEst: string; -}; - -export type SendTokenFormProps = { - coinType: string; - onSubmit: (values: SubmitProps) => void; - initialAmount: string; - initialTo: string; -}; - -function totalBalance(coins: CoinStruct[]): bigint { - return coins.reduce((partialSum, c) => partialSum + getBalanceFromCoinStruct(c), BigInt(0)); -} -function getBalanceFromCoinStruct(coin: CoinStruct): bigint { - return BigInt(coin.balance); -} - -function GasBudgetEstimation({ - coinDecimals, - coins, -}: { - coinDecimals: number; - coins: CoinStruct[]; -}) { - const activeAddress = useActiveAddress(); - const { values, setFieldValue } = useFormikContext(); - const suiNSEnabled = useSuiNSEnabled(); - - const client = useSuiClient(); - const { data: gasBudget } = useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: [ - 'transaction-gas-budget-estimate', - { - to: values.to, - amount: values.amount, - coins, - activeAddress, - coinDecimals, - }, - ], - queryFn: async () => { - if (!values.amount || !values.to || !coins || !activeAddress) { - return null; - } - - let to = values.to; - if (suiNSEnabled && isValidSuiNSName(values.to)) { - const address = await client.resolveNameServiceAddress({ - name: values.to, - }); - if (!address) { - throw new Error('SuiNS name not found.'); - } - to = address; - } - - const tx = createTokenTransferTransaction({ - to, - amount: values.amount, - coinType: SUI_TYPE_ARG, - coinDecimals, - isPayAllSui: values.isPayAllSui, - coins, - }); - - tx.setSender(activeAddress); - await tx.build({ client }); - return tx.blockData.gasConfig.budget; - }, - }); - - const [formattedGas] = useFormatCoin(gasBudget, SUI_TYPE_ARG); - - // gasBudgetEstimation should change when the amount above changes - useEffect(() => { - setFieldValue('gasBudgetEst', formattedGas, true); - }, [formattedGas, setFieldValue, values.amount]); - - return ( -
    -
    - - Estimated Gas Fees - -
    - - {formattedGas ? formattedGas + ' ' + GAS_SYMBOL : '--'} - -
    - ); -} - -// Set the initial gasEstimation from initial amount -// base on the input amount field update the gasEstimation value -// Separating the gasEstimation from the formik context to access the input amount value and update the gasEstimation value -export function SendTokenForm({ - coinType, - onSubmit, - initialAmount = '', - initialTo = '', -}: SendTokenFormProps) { - const client = useSuiClient(); - const activeAddress = useActiveAddress(); - // Get all coins of the type - const { data: coinsData, isPending: coinsIsPending } = useGetAllCoins(coinType, activeAddress!); - - const { data: suiCoinsData, isPending: suiCoinsIsPending } = useGetAllCoins( - SUI_TYPE_ARG, - activeAddress!, - ); - - const suiCoins = suiCoinsData; - const coins = coinsData; - const coinBalance = totalBalance(coins || []); - const suiBalance = totalBalance(suiCoins || []); - - const coinMetadata = useCoinMetadata(coinType); - const coinDecimals = coinMetadata.data?.decimals ?? 0; - - const [tokenBalance, symbol, queryResult] = useFormatCoin(coinBalance, coinType, CoinFormat.FULL); - const suiNSEnabled = useSuiNSEnabled(); - - const validationSchemaStepOne = useMemo( - () => createValidationSchemaStepOne(client, suiNSEnabled, coinBalance, symbol, coinDecimals), - [client, coinBalance, symbol, coinDecimals, suiNSEnabled], - ); - - // remove the comma from the token balance - const formattedTokenBalance = tokenBalance.replace(/,/g, ''); - const initAmountBig = parseAmount(initialAmount, coinDecimals); - - return ( - - { - if (!coins || !suiCoins) return; - const coinsIDs = [...coins] - .sort((a, b) => Number(b.balance) - Number(a.balance)) - .map(({ coinObjectId }) => coinObjectId); - - if (suiNSEnabled && isValidSuiNSName(to)) { - const address = await client.resolveNameServiceAddress({ - name: to, - }); - if (!address) { - throw new Error('SuiNS name not found.'); - } - to = address; - } - - const data = { - to, - amount, - isPayAllSui, - coins, - coinIds: coinsIDs, - gasBudgetEst, - }; - onSubmit(data); - }} - > - {({ isValid, isSubmitting, setFieldValue, values, submitForm, validateField }) => { - const newPaySuiAll = - parseAmount(values.amount, coinDecimals) === coinBalance && coinType === SUI_TYPE_ARG; - if (values.isPayAllSui !== newPaySuiAll) { - setFieldValue('isPayAllSui', newPaySuiAll); - } - - const hasEnoughBalance = - values.isPayAllSui || - suiBalance > - parseAmount(values.gasBudgetEst, coinDecimals) + - parseAmount(coinType === SUI_TYPE_ARG ? values.amount : '0', coinDecimals); - - return ( - - -
    -
    -
    - - Select Coin Amount to Send - -
    - - { - // using await to make sure the value is set before the validation - await setFieldValue('amount', formattedTokenBalance); - validateField('amount'); - }} - actionDisabled={ - parseAmount(values?.amount, coinDecimals) === coinBalance || - queryResult.isPending || - !coinBalance - } - /> -
    - {!hasEnoughBalance && isValid ? ( -
    - Insufficient SUI to cover transaction -
    - ) : null} - - {coins ? : null} - -
    -
    - - Enter Recipient Address - -
    -
    - -
    -
    - -
    - - -
    - ); - }} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/index.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/index.tsx deleted file mode 100644 index 48540b5f9ea3a..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/index.tsx +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import BottomMenuLayout, { Content, Menu } from '_app/shared/bottom-menu-layout'; -import { Button } from '_app/shared/ButtonUI'; -import { Text } from '_app/shared/text'; -import { ActiveCoinsCard } from '_components/active-coins-card'; -import Overlay from '_components/overlay'; -import { ampli } from '_src/shared/analytics/ampli'; -import { getSignerOperationErrorMessage } from '_src/ui/app/helpers/errorMessages'; -import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; -import { useQredoTransaction } from '_src/ui/app/hooks/useQredoTransaction'; -import { useSigner } from '_src/ui/app/hooks/useSigner'; -import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { QredoActionIgnoredByUser } from '_src/ui/app/QredoSigner'; -import { useCoinMetadata } from '@mysten/core'; -import { ArrowLeft16, ArrowRight16 } from '@mysten/icons'; -import * as Sentry from '@sentry/react'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { useMemo, useState } from 'react'; -import { toast } from 'react-hot-toast'; -import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; - -import { PreviewTransfer } from './PreviewTransfer'; -import { SendTokenForm } from './SendTokenForm'; -import type { SubmitProps } from './SendTokenForm'; -import { createTokenTransferTransaction } from './utils/transaction'; - -function TransferCoinPage() { - const [searchParams] = useSearchParams(); - const coinType = searchParams.get('type'); - const [showTransactionPreview, setShowTransactionPreview] = useState(false); - const [formData, setFormData] = useState(); - const navigate = useNavigate(); - const { data: coinMetadata } = useCoinMetadata(coinType); - const activeAccount = useActiveAccount(); - const signer = useSigner(activeAccount); - const address = activeAccount?.address; - const queryClient = useQueryClient(); - const { clientIdentifier, notificationModal } = useQredoTransaction(); - - const transaction = useMemo(() => { - if (!coinType || !signer || !formData || !address) return null; - - return createTokenTransferTransaction({ - coinType, - coinDecimals: coinMetadata?.decimals ?? 0, - ...formData, - }); - }, [formData, signer, coinType, address, coinMetadata?.decimals]); - - const executeTransfer = useMutation({ - mutationFn: async () => { - if (!transaction || !signer) { - throw new Error('Missing data'); - } - - const sentryTransaction = Sentry.startTransaction({ - name: 'send-tokens', - }); - try { - return signer.signAndExecuteTransactionBlock( - { - transactionBlock: transaction, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }, - clientIdentifier, - ); - } catch (error) { - if (!(error instanceof QredoActionIgnoredByUser)) { - sentryTransaction.setTag('failure', true); - } - throw error; - } finally { - sentryTransaction.finish(); - } - }, - onSuccess: (response) => { - queryClient.invalidateQueries({ queryKey: ['get-coins'] }); - queryClient.invalidateQueries({ queryKey: ['coin-balance'] }); - - ampli.sentCoins({ - coinType: coinType!, - }); - - const receiptUrl = `/receipt?txdigest=${encodeURIComponent( - response.digest, - )}&from=transactions`; - return navigate(receiptUrl); - }, - onError: (error) => { - if (error instanceof QredoActionIgnoredByUser) { - navigate('/'); - } else { - toast.error( -
    - - {getSignerOperationErrorMessage(error)} - -
    , - ); - } - }, - }); - - if (useUnlockedGuard()) { - return null; - } - - if (!coinType) { - return ; - } - - return ( - navigate('/')} - > -
    - {showTransactionPreview && formData ? ( - - - - - - - - ) : ( - <> -
    -
    - - Select all Coins - -
    - -
    - - { - setShowTransactionPreview(true); - setFormData(formData); - }} - coinType={coinType} - initialAmount={formData?.amount || ''} - initialTo={formData?.to || ''} - /> - - )} -
    - {notificationModal} -
    - ); -} - -export default TransferCoinPage; diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts b/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts deleted file mode 100644 index 2a593b63ed836..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { parseAmount } from '_src/ui/app/helpers'; -import { type CoinStruct } from '@mysten/sui/client'; -import { Transaction } from '@mysten/sui/transactions'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -interface Options { - coinType: string; - to: string; - amount: string; - coinDecimals: number; - isPayAllSui: boolean; - coins: CoinStruct[]; -} - -export function createTokenTransferTransaction({ - to, - amount, - coins, - coinType, - coinDecimals, - isPayAllSui, -}: Options) { - const tx = new Transaction(); - - if (isPayAllSui && coinType === SUI_TYPE_ARG) { - tx.transferObjects([tx.gas], to); - tx.setGasPayment( - coins - .filter((coin) => coin.coinType === coinType) - .map((coin) => ({ - objectId: coin.coinObjectId, - digest: coin.digest, - version: coin.version, - })), - ); - - return tx; - } - - const bigIntAmount = parseAmount(amount, coinDecimals); - const [primaryCoin, ...mergeCoins] = coins.filter((coin) => coin.coinType === coinType); - - if (coinType === SUI_TYPE_ARG) { - const coin = tx.splitCoins(tx.gas, [bigIntAmount]); - tx.transferObjects([coin], to); - } else { - const primaryCoinInput = tx.object(primaryCoin.coinObjectId); - if (mergeCoins.length) { - // TODO: This could just merge a subset of coins that meet the balance requirements instead of all of them. - tx.mergeCoins( - primaryCoinInput, - mergeCoins.map((coin) => tx.object(coin.coinObjectId)), - ); - } - const coin = tx.splitCoins(primaryCoinInput, [bigIntAmount]); - tx.transferObjects([coin], to); - } - - return tx; -} diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts b/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts deleted file mode 100644 index 3686d5f76d6f5..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { createSuiAddressValidation } from '_components/address-input/validation'; -import { createTokenValidation } from '_src/shared/validation'; -import { type SuiClient } from '@mysten/sui/client'; -import * as Yup from 'yup'; - -export function createValidationSchemaStepOne( - client: SuiClient, - suiNSEnabled: boolean, - ...args: Parameters -) { - return Yup.object({ - to: createSuiAddressValidation(client, suiNSEnabled), - amount: createTokenValidation(...args), - }); -} diff --git a/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromo.tsx b/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromo.tsx deleted file mode 100644 index 4278c317898e3..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromo.tsx +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { Button } from '_app/shared/ButtonUI'; -import { Heading } from '_app/shared/heading'; -import PageTitle from '_app/shared/PageTitle'; -import { Text } from '_app/shared/text'; -import { useUsdcPromo } from '_pages/home/usdc-promo/useUsdcPromo'; -import { USDC_TYPE_ARG } from '_pages/swap/utils'; -import { ampli } from '_shared/analytics/ampli'; -import { useNavigate, useSearchParams } from 'react-router-dom'; - -export function UsdcPromo() { - const navigate = useNavigate(); - const [searchParams] = useSearchParams(); - const fromCoinType = searchParams.get('type'); - const presetAmount = searchParams.get('presetAmount'); - const { promoBannerSheetTitle, promoBannerSheetContent, ctaLabel } = useUsdcPromo(); - - return ( -
    - - USDC -
    - - {promoBannerSheetTitle} - - - {promoBannerSheetContent} - -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromoBanner.tsx b/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromoBanner.tsx deleted file mode 100644 index a7e11395014c5..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/usdc-promo/UsdcPromoBanner.tsx +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useGetAllBalances } from '_app/hooks/useGetAllBalances'; -import { Text } from '_app/shared/text'; -import { ButtonOrLink } from '_app/shared/utils/ButtonOrLink'; -import { useActiveAddress } from '_hooks'; -import { useUsdcPromo } from '_pages/home/usdc-promo/useUsdcPromo'; -import { ampli } from '_shared/analytics/ampli'; -import { useCoinMetadata } from '@mysten/core'; -import { type CoinBalance } from '@mysten/sui/client'; -import BigNumber from 'bignumber.js'; -import { useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; - -function useUsdcInUserBalance() { - const activeAccountAddress = useActiveAddress(); - const { wrappedUsdcList } = useUsdcPromo(); - - const { data: coinBalances } = useGetAllBalances(activeAccountAddress || ''); - - return coinBalances - ? coinBalances.filter( - (coin) => wrappedUsdcList.includes(coin.coinType) && Number(coin.totalBalance) > 0, - ) - : []; -} - -function BannerImage({ balance }: { balance: CoinBalance }) { - const navigate = useNavigate(); - const { promoBannerBackground, promoBannerText } = useUsdcPromo(); - const { data: metadata } = useCoinMetadata(balance.coinType); - const usdcInUsersBalance = useUsdcInUserBalance(); - - const maxBalance = useMemo(() => { - const decimals = metadata?.decimals ?? 0; - return new BigNumber(balance?.totalBalance || 0) - .shiftedBy(-decimals) - .decimalPlaces(decimals) - .toString(); - }, [balance, metadata]); - - return ( - { - ampli.clickedUsdcPromoBanner({ - wUsdcInAccount: usdcInUsersBalance.map((coin) => coin.coinType), - }); - navigate( - `/usdc-promo?${new URLSearchParams({ - type: balance.coinType, - presetAmount: maxBalance, - })}`, - ); - }} - > - USDC Promo -
    - USDC - - {promoBannerText} - -
    -
    - ); -} - -export function UsdcPromoBanner() { - const { enabled } = useUsdcPromo(); - const usdcInUsersBalance = useUsdcInUserBalance(); - - const firstUsdcInUsersBalance = usdcInUsersBalance[0]; - - if (!enabled || !firstUsdcInUsersBalance) { - return null; - } - - return ; -} diff --git a/apps/wallet/src/ui/app/pages/home/usdc-promo/useUsdcPromo.ts b/apps/wallet/src/ui/app/pages/home/usdc-promo/useUsdcPromo.ts deleted file mode 100644 index 66992175f7f9e..0000000000000 --- a/apps/wallet/src/ui/app/pages/home/usdc-promo/useUsdcPromo.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useFeatureIsOn, useFeatureValue } from '@growthbook/growthbook-react'; - -type WalletUsdcPromo = { - promoBannerImage: string; - promoBannerBackground: string; - promoBannerText: string; - promoBannerSheetTitle: string; - promoBannerSheetContent: string; - ctaLabel: string; - wrappedUsdcList: string[]; -}; - -export function useUsdcPromo() { - const enabled = useFeatureIsOn('wallet-usdc-promo-enabled'); - const dynamicConfigs = useFeatureValue('wallet-usdc-promo', { - promoBannerImage: '', - promoBannerBackground: '', - promoBannerText: '', - promoBannerSheetTitle: '', - promoBannerSheetContent: '', - ctaLabel: '', - wrappedUsdcList: [], - }); - - return { - ...dynamicConfigs, - enabled, - }; -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/QredoConnectInfoPage.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/QredoConnectInfoPage.tsx deleted file mode 100644 index 9c270d74359d0..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/QredoConnectInfoPage.tsx +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { LabelValueItem } from '_components/LabelValueItem'; -import { LabelValuesContainer } from '_components/LabelValuesContainer'; -import { SummaryCard } from '_components/SummaryCard'; -import { UserApproveContainer } from '_components/user-approve-container'; -import { useEffect, useState } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; - -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { Heading } from '../../shared/heading'; -import { PageMainLayoutTitle } from '../../shared/page-main-layout/PageMainLayoutTitle'; -import { Text } from '../../shared/text'; -import { useQredoUIPendingRequest } from './hooks'; -import { isUntrustedQredoConnect } from './utils'; - -export function QredoConnectInfoPage() { - const { requestID } = useParams(); - const { data, isPending } = useQredoUIPendingRequest(requestID); - const isUntrusted = !!data && isUntrustedQredoConnect(data); - const [isUntrustedAccepted, setIsUntrustedAccepted] = useState(false); - const navigate = useNavigate(); - const backgroundService = useBackgroundClient(); - useEffect(() => { - if (!isPending && !data) { - window.close(); - } - }, [isPending, data]); - if (isPending) { - return null; - } - if (!data) { - return null; - } - const showUntrustedWarning = isUntrusted && !isUntrustedAccepted; - return ( - <> - - { - if (approved) { - if (showUntrustedWarning) { - setIsUntrustedAccepted(true); - } else { - navigate('./select', { state: { reviewed: true } }); - } - } else { - await backgroundService.rejectQredoConnection({ - qredoID: data.id, - }); - window.close(); - } - }} - addressHidden - > -
    - - - Your Connection Is Not Secure - - - If you connect your wallet with this site your data could be exposed to - attackers. - -
    - - Click **Reject** if you don't trust this site. Continue at your own risk. - -
    -
    - ) : ( - - - - - - - ) - } - /> -
    - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/SelectQredoAccountsPage.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/SelectQredoAccountsPage.tsx deleted file mode 100644 index 7dbf2886f3d54..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/SelectQredoAccountsPage.tsx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Overlay from '_components/overlay'; -import { type Wallet } from '_src/shared/qredo-api'; -import { ArrowRight16 } from '@mysten/icons'; -import { useEffect, useState } from 'react'; -import { Navigate, useLocation, useNavigate, useParams } from 'react-router-dom'; - -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; -import { Button } from '../../shared/ButtonUI'; -import { SelectQredoAccountsSummaryCard } from './components/SelectQredoAccountsSummaryCard'; -import { useQredoUIPendingRequest } from './hooks'; - -export function SelectQredoAccountsPage() { - const { id } = useParams(); - const { state } = useLocation(); - const navigate = useNavigate(); - const qredoRequestReviewed = !!state?.reviewed; - const { data: qredoPendingRequest, isPending: isQredoRequestLoading } = - useQredoUIPendingRequest(id); - // do not call the api if user has not clicked continue in Qredo Connect Info page - const fetchAccountsEnabled = - !isQredoRequestLoading && (!qredoPendingRequest || qredoRequestReviewed); - const [selectedAccounts, setSelectedAccounts] = useState([]); - const shouldCloseWindow = (!isQredoRequestLoading && !qredoPendingRequest) || !id; - const [, setAccountsFormValues] = useAccountsFormContext(); - useEffect(() => { - if (shouldCloseWindow) { - window.close(); - } - }, [shouldCloseWindow]); - if (qredoPendingRequest && !qredoRequestReviewed) { - return ; - } - if (shouldCloseWindow) { - return null; - } - return ( - { - navigate(-1); - }} - > -
    -
    - -
    -
    -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx deleted file mode 100644 index adcb7b814f001..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Wallet } from '_src/shared/qredo-api'; -import { BadgeLabel } from '_src/ui/app/components/BadgeLabel'; -import { Text } from '_src/ui/app/shared/text'; -import { CheckFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui/utils'; -import cn from 'clsx'; - -export type QredoAccountItemProps = Wallet & { - selected: boolean; - onClick: () => void; -}; - -export function QredoAccountItem({ selected, address, onClick, labels }: QredoAccountItemProps) { - return ( -
    - -
    - {formatAddress(address)} - {labels.length ? ( -
    - {labels.map(({ key, value }) => ( - - ))} -
    - ) : null} -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountsSelector.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountsSelector.tsx deleted file mode 100644 index d2995e33e637a..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountsSelector.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Wallet } from '_src/shared/qredo-api'; -import { Search16 } from '@mysten/icons'; -import { useState } from 'react'; - -import { QredoAccountItem } from './QredoAccountItem'; - -function matchesSearchTerm({ walletID, address, labels }: Wallet, searchTerm: string) { - const term = searchTerm.trim().toLowerCase(); - return ( - !term || - walletID.toLowerCase().includes(term) || - address.toLowerCase().includes(term) || - labels.some(({ value }) => value.toLowerCase().includes(term)) - ); -} - -function isAccountSelected(selectedAccounts: Wallet[], account: Wallet) { - return selectedAccounts.some(({ walletID }) => account.walletID === walletID); -} - -export type QredoAccountsSelectorProps = { - accounts: Wallet[]; - selectedAccounts: Wallet[]; - onChange: (selectedAccounts: Wallet[]) => void; -}; - -export function QredoAccountsSelector({ - accounts, - selectedAccounts, - onChange, -}: QredoAccountsSelectorProps) { - const [searchTerm, setSearchTerm] = useState(''); - return ( - <> -
    - setSearchTerm(e.target.value)} - value={searchTerm} - placeholder="Search" - /> - -
    -
    - {accounts - .filter((aWallet) => matchesSearchTerm(aWallet, searchTerm)) - .map((aWallet) => ( - { - const isSelected = isAccountSelected(selectedAccounts, aWallet); - let newAccounts = [...selectedAccounts]; - if (isSelected) { - newAccounts = newAccounts.filter(({ walletID }) => aWallet.walletID !== walletID); - } else { - newAccounts.push(aWallet); - } - onChange(newAccounts); - }} - /> - ))} -
    - - ); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/components/SelectQredoAccountsSummaryCard.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/components/SelectQredoAccountsSummaryCard.tsx deleted file mode 100644 index 3dd952e018840..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/components/SelectQredoAccountsSummaryCard.tsx +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Alert from '_components/alert'; -import Loading from '_components/loading'; -import { SummaryCard } from '_components/SummaryCard'; -import { isQredoAccountSerializedUI } from '_src/background/accounts/QredoAccount'; -import { type Wallet } from '_src/shared/qredo-api'; -import { useAccounts } from '_src/ui/app/hooks/useAccounts'; -import { Link } from '_src/ui/app/shared/Link'; -import { useEffect, useMemo, useRef } from 'react'; - -import { useFetchQredoAccounts } from '../hooks'; -import { QredoAccountsSelector } from './QredoAccountsSelector'; - -export type SelectQredoAccountsSummaryCardProps = { - qredoID: string; - fetchAccountsEnabled: boolean; - selectedAccounts: Wallet[]; - onChange: (selectedAccounts: Wallet[]) => void; -}; - -export function SelectQredoAccountsSummaryCard({ - qredoID, - fetchAccountsEnabled = false, - selectedAccounts, - onChange, -}: SelectQredoAccountsSummaryCardProps) { - const { data, isPending, error } = useFetchQredoAccounts(qredoID, fetchAccountsEnabled); - const { data: allAccounts } = useAccounts(); - const qredoConnectedAccounts = useMemo( - () => allAccounts?.filter(isQredoAccountSerializedUI) || null, - [allAccounts], - ); - const selectedAccountRef = useRef(selectedAccounts); - selectedAccountRef.current = selectedAccounts; - useEffect(() => { - if (qredoConnectedAccounts?.length && data?.length) { - const newSelected = [...selectedAccountRef.current]; - data - .filter(({ walletID }) => { - for (const aConnectedAccount of qredoConnectedAccounts) { - if (aConnectedAccount.walletID === walletID) { - return true; - } - } - return false; - }) - .forEach((aConnectedWallet) => { - if ( - !selectedAccountRef.current.find( - ({ walletID }) => walletID === aConnectedWallet.walletID, - ) - ) { - newSelected.push(aConnectedWallet); - } - }); - if (newSelected.length !== selectedAccountRef.current.length) { - onChange(newSelected); - } - } - }, [qredoConnectedAccounts, data, onChange]); - return ( - - {error ? ( - Failed to fetch accounts. Please try again later. - ) : data?.length ? ( - - ) : ( - No accounts found - )} - - } - footer={ -
    - { - if (data) { - onChange([...data]); - } - }} - disabled={!data?.length} - /> -
    - } - /> - ); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/hooks.ts b/apps/wallet/src/ui/app/pages/qredo-connect/hooks.ts deleted file mode 100644 index 2dc2d1aaf6341..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/hooks.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type GetWalletsParams } from '_src/shared/qredo-api'; -import { useQuery } from '@tanstack/react-query'; - -import { useBackgroundClient } from '../../hooks/useBackgroundClient'; -import { useQredoAPI } from '../../hooks/useQredoAPI'; - -export function useQredoUIPendingRequest(requestID?: string) { - const backgroundClient = useBackgroundClient(); - return useQuery({ - queryKey: ['qredo-connect', 'pending-request', requestID], - queryFn: async () => await backgroundClient.fetchPendingQredoConnectRequest(requestID!), - staleTime: 0, - refetchInterval: 1000, - enabled: !!requestID, - meta: { skipPersistedCache: true }, - }); -} - -export function useFetchQredoAccounts( - qredoID: string, - enabled?: boolean, - params?: GetWalletsParams, -) { - const [api, isAPILoading, apiInitError] = useQredoAPI(qredoID); - return useQuery({ - queryKey: ['qredo', 'fetch', 'accounts', qredoID, api, apiInitError], - queryFn: async () => { - if (api) { - return (await api.getWallets(params)).wallets; - } - throw apiInitError ? apiInitError : new Error('Qredo API initialization failed'); - }, - enabled: !!qredoID && (enabled ?? true) && !isAPILoading && !!(api || apiInitError), - }); -} diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/utils.ts b/apps/wallet/src/ui/app/pages/qredo-connect/utils.ts deleted file mode 100644 index 3712f3be7feca..0000000000000 --- a/apps/wallet/src/ui/app/pages/qredo-connect/utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type UIQredoPendingRequest } from '_src/background/qredo/types'; - -export function isUntrustedQredoConnect({ apiUrl, origin }: UIQredoPendingRequest) { - try { - return new URL(origin).protocol !== 'https:' || new URL(apiUrl).protocol !== 'https:'; - } catch (e) { - return false; - } -} diff --git a/apps/wallet/src/ui/app/pages/restricted/SadCapy.svg b/apps/wallet/src/ui/app/pages/restricted/SadCapy.svg deleted file mode 100644 index 45adacbae2d2e..0000000000000 --- a/apps/wallet/src/ui/app/pages/restricted/SadCapy.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/wallet/src/ui/app/pages/restricted/index.tsx b/apps/wallet/src/ui/app/pages/restricted/index.tsx deleted file mode 100644 index ad72e82f1ccb4..0000000000000 --- a/apps/wallet/src/ui/app/pages/restricted/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useInitializedGuard } from '../../hooks'; -import { Text } from '../../shared/text'; -import SadCapy from './SadCapy.svg'; - -export function RestrictedPage() { - useInitializedGuard(true); - - return ( -
    - - - Regrettably this service is not available to you. Applicable laws prohibit us from providing - our services to your location at this time. - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/site-connect/SiteConnectPage.module.scss b/apps/wallet/src/ui/app/pages/site-connect/SiteConnectPage.module.scss deleted file mode 100644 index 7de0f54e7c225..0000000000000 --- a/apps/wallet/src/ui/app/pages/site-connect/SiteConnectPage.module.scss +++ /dev/null @@ -1,39 +0,0 @@ -@use '_utils'; -@use '_values/colors'; -@use '_variables' as v; - -.label { - border-top: 1px solid colors.$gray-45; - padding-top: 20px; - padding-bottom: 10px; - text-transform: uppercase; - color: colors.$gray-75; - font-weight: 600; - font-size: 12px; - line-height: 15px; -} - -.warning-wrapper { - margin-bottom: 8px; - display: flex; - justify-content: space-around; - color: colors.$sui-steel-darker; -} - -.warning-title { - @include utils.typography('Primary/Body-SB'); - - display: inline-block; - margin-bottom: -1px; - padding-bottom: 8px; -} - -.warning-message { - @include utils.typography('Primary/BodySmall-M'); - - color: colors.$gray-80; - background-color: colors.$white; - padding: 20px; - border-radius: 16px; - box-shadow: v.use(v.$shadows-message-content); -} diff --git a/apps/wallet/src/ui/app/pages/site-connect/index.tsx b/apps/wallet/src/ui/app/pages/site-connect/index.tsx deleted file mode 100644 index a5ef01bb2f30f..0000000000000 --- a/apps/wallet/src/ui/app/pages/site-connect/index.tsx +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { AccountItemApproveConnection } from '_components/accounts/AccountItemApproveConnection'; -import Loading from '_components/loading'; -import { UserApproveContainer } from '_components/user-approve-container'; -import { useAppDispatch, useAppSelector } from '_hooks'; -import type { RootState } from '_redux/RootReducer'; -import { permissionsSelectors, respondToPermissionRequest } from '_redux/slices/permissions'; -import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { ampli } from '_src/shared/analytics/ampli'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { useParams } from 'react-router-dom'; - -import { AccountMultiSelectWithControls } from '../../components/accounts/AccountMultiSelect'; -import Alert from '../../components/alert'; -import { SectionHeader } from '../../components/SectionHeader'; -import { useAccountGroups } from '../../hooks/useAccountGroups'; -import { useActiveAccount } from '../../hooks/useActiveAccount'; -import { PageMainLayoutTitle } from '../../shared/page-main-layout/PageMainLayoutTitle'; -import st from './SiteConnectPage.module.scss'; - -function SiteConnectPage() { - const { requestID } = useParams(); - const permissionsInitialized = useAppSelector(({ permissions }) => permissions.initialized); - const loading = !permissionsInitialized; - const permissionSelector = useMemo( - () => (state: RootState) => - requestID ? permissionsSelectors.selectById(state, requestID) : null, - [requestID], - ); - const dispatch = useAppDispatch(); - const permissionRequest = useAppSelector(permissionSelector); - const activeAccount = useActiveAccount(); - const accountGroups = useAccountGroups(); - const accounts = accountGroups.list(); - const unlockedAccounts = accounts.filter((account) => !account.isLocked); - const lockedAccounts = accounts.filter((account) => account.isLocked); - const [accountsToConnect, setAccountsToConnect] = useState(() => - activeAccount && !activeAccount.isLocked ? [activeAccount] : [], - ); - const handleOnSubmit = useCallback( - async (allowed: boolean) => { - if (requestID && accountsToConnect && permissionRequest) { - await dispatch( - respondToPermissionRequest({ - id: requestID, - accounts: allowed ? accountsToConnect.map((account) => account.address) : [], - allowed, - }), - ); - ampli.respondedToConnectionRequest({ - applicationName: permissionRequest.name, - applicationUrl: permissionRequest.origin, - approvedConnection: allowed, - }); - window.close(); - } - }, - [requestID, accountsToConnect, permissionRequest, dispatch], - ); - useEffect(() => { - if (!loading && !permissionRequest) { - window.close(); - } - }, [loading, permissionRequest]); - - const parsedOrigin = useMemo( - () => (permissionRequest ? new URL(permissionRequest.origin) : null), - [permissionRequest], - ); - - const isSecure = parsedOrigin?.protocol === 'https:'; - const [displayWarning, setDisplayWarning] = useState(!isSecure); - - const handleHideWarning = useCallback( - async (allowed: boolean) => { - if (allowed) { - setDisplayWarning(false); - } else { - await handleOnSubmit(false); - } - }, - [handleOnSubmit], - ); - - useEffect(() => { - setDisplayWarning(!isSecure); - }, [isSecure]); - return ( - - {permissionRequest && - (displayWarning ? ( - - -
    -

    Your Connection is Not Secure

    -
    - -
    - If you connect your wallet to this site your data could be exposed to attackers. Click - **Reject** if you don't trust this site. -
    -
    - Continue at your own risk. -
    -
    - ) : ( - - -
    - {unlockedAccounts.length > 0 ? ( - account.id)} - accounts={unlockedAccounts ?? []} - onChange={(value) => { - setAccountsToConnect(value.map((id) => accounts?.find((a) => a.id === id)!)); - }} - /> - ) : ( - - All accounts are currently locked. Unlock accounts to connect. - - )} - {lockedAccounts?.length > 0 && ( -
    - - {lockedAccounts?.map((account) => ( - - ))} -
    - )} -
    -
    - ))} -
    - ); -} - -export default SiteConnectPage; diff --git a/apps/wallet/src/ui/app/pages/swap/AssetData.tsx b/apps/wallet/src/ui/app/pages/swap/AssetData.tsx deleted file mode 100644 index a4fb234bd289b..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/AssetData.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useActiveAccount } from '_app/hooks/useActiveAccount'; -import { Heading } from '_app/shared/heading'; -import { Text } from '_app/shared/text'; -import { ButtonOrLink } from '_app/shared/utils/ButtonOrLink'; -import { CoinIcon } from '_components/coin-icon'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { useGetBalance } from '_pages/swap/utils'; -import { useCoinMetadata } from '@mysten/core'; -import { ChevronDown16 } from '@mysten/icons'; - -export function AssetData({ - coinType, - to, - onClick, - disabled, -}: { - coinType: string; - to?: string; - onClick?: () => void; - disabled?: boolean; -}) { - const activeAccount = useActiveAccount(); - const currentAddress = activeAccount?.address; - - const { data: balance } = useGetBalance({ - coinType, - owner: currentAddress, - }); - - const { data: coinMetadata } = useCoinMetadata(coinType); - - return ( - - {!!coinType && } - - {coinMetadata?.symbol || 'Select coin'} - - {!disabled && } - - } - > - {!!balance && ( -
    -
    Balance
    {' '} - - {balance?.formatted} {coinMetadata?.symbol} - -
    - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/AverageSection.tsx b/apps/wallet/src/ui/app/pages/swap/AverageSection.tsx deleted file mode 100644 index e5ae0c56d28cd..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/AverageSection.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { Text } from '_app/shared/text'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { MAX_FLOAT, SUI_USDC_AVERAGE_CONVERSION_RATE } from '_pages/swap/constants'; -import { useSwapData } from '_pages/swap/utils'; -import BigNumber from 'bignumber.js'; - -interface AverageSectionProps { - averages: { - averageBaseToQuote: string; - averageQuoteToBase: string; - }; - isAsk: boolean; - baseCoinType: string; - quoteCoinType: string; -} - -export function AverageSection({ - averages, - baseCoinType, - quoteCoinType, - isAsk, -}: AverageSectionProps) { - const { baseCoinMetadata, quoteCoinMetadata } = useSwapData({ - baseCoinType, - quoteCoinType, - }); - - const baseCoinSymbol = baseCoinMetadata.data?.symbol; - const quoteCoinSymbol = quoteCoinMetadata.data?.symbol; - - return ( -
    - Estimated Rate}> - - 1 {isAsk ? baseCoinSymbol : quoteCoinSymbol} ≈{' '} - {new BigNumber(isAsk ? averages.averageBaseToQuote : averages.averageQuoteToBase) - .shiftedBy(isAsk ? SUI_USDC_AVERAGE_CONVERSION_RATE : -SUI_USDC_AVERAGE_CONVERSION_RATE) - .decimalPlaces(MAX_FLOAT) - .toString()}{' '} - {isAsk ? quoteCoinSymbol : baseCoinSymbol} - - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/CoinsSelectionPage.tsx b/apps/wallet/src/ui/app/pages/swap/CoinsSelectionPage.tsx deleted file mode 100644 index f49bb2e9edacd..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/CoinsSelectionPage.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useGetAllBalances } from '_app/hooks/useGetAllBalances'; -import { useValidSwapTokensList } from '_app/hooks/useValidSwapTokensList'; -import Loading from '_components/loading'; -import Overlay from '_components/overlay'; -import { useActiveAddress, useSortedCoinsByCategories } from '_hooks'; -import { TokenRow } from '_pages/home/tokens/TokensDetails'; -import { normalizeStructTag } from '@mysten/sui/utils'; -import { Fragment } from 'react'; -import { useNavigate, useSearchParams } from 'react-router-dom'; - -export function CoinsSelectionPage() { - const navigate = useNavigate(); - const selectedAddress = useActiveAddress(); - const [searchParams] = useSearchParams(); - const fromCoinType = searchParams.get('fromCoinType'); - const toCoinType = searchParams.get('toCoinType'); - const source = searchParams.get('source'); - const currentAmount = searchParams.get('currentAmount'); - - const { data: swapFromTokensList, isLoading } = useValidSwapTokensList(); - const swapToTokensList = swapFromTokensList.filter((token) => { - if (!fromCoinType) { - return true; - } - return normalizeStructTag(token) !== normalizeStructTag(fromCoinType); - }); - - const allowedCoinTypes = source === 'fromCoinType' ? swapFromTokensList : swapToTokensList; - - const { data: coinBalances, isPending } = useGetAllBalances(selectedAddress || ''); - - const { recognized } = useSortedCoinsByCategories(coinBalances ?? []); - - return ( - navigate(-1)}> - -
    - {allowedCoinTypes.map((coinType, index) => { - const coinBalance = recognized?.find((coin) => coin.coinType === coinType) || {}; - const totalBalance = - coinBalances?.find( - (balance) => normalizeStructTag(balance.coinType) === normalizeStructTag(coinType), - )?.totalBalance ?? '0'; - - return ( - - { - const params = fromCoinType - ? { type: fromCoinType, toType: coinType, presetAmount: currentAmount || '0' } - : { - type: coinType, - toType: toCoinType || '', - presetAmount: currentAmount || '0', - }; - navigate(`/swap?${new URLSearchParams(params)}`); - }} - /> - -
    - - ); - })} -
    - - - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx b/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx deleted file mode 100644 index c6052c6925b77..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { Text } from '_app/shared/text'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { DEFAULT_WALLET_FEE_ADDRESS, WALLET_FEES_PERCENTAGE } from '_pages/swap/constants'; -import { getUSDCurrency } from '_pages/swap/utils'; -import { GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; -import { FEATURES } from '_shared/experimentation/features'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { useBalanceInUSD, useFormatCoin } from '@mysten/core'; -import { type BalanceChange } from '@mysten/sui/client'; - -export function GasFeeSection({ - activeCoinType, - totalGas, - isValid, - balanceChanges, -}: { - activeCoinType: string | null; - isValid: boolean; - totalGas: string; - balanceChanges: BalanceChange[]; -}) { - const walletFeeAddress = useFeatureValue(FEATURES.WALLET_FEE_ADDRESS, DEFAULT_WALLET_FEE_ADDRESS); - const estimatedAccessFeesBalance = balanceChanges.find( - (change) => - 'owner' in change && - typeof change.owner === 'object' && - 'AddressOwner' in change.owner && - change.owner.AddressOwner === walletFeeAddress, - )?.amount; - const [formattedEstimatedFees, balanceSymbol] = useFormatCoin( - estimatedAccessFeesBalance, - activeCoinType, - ); - const usdValue = useBalanceInUSD(activeCoinType || '', estimatedAccessFeesBalance || ''); - const [gas, symbol] = useFormatCoin(totalGas, GAS_TYPE_ARG); - - return ( -
    - - Access Fees ({WALLET_FEES_PERCENTAGE}%) - - } - > - - {formattedEstimatedFees - ? `${formattedEstimatedFees} ${balanceSymbol} (${getUSDCurrency(usdValue)})` - : '--'} - - - -
    - - - Estimated Gas Fee - - } - > - - {totalGas && isValid ? `${gas} ${symbol}` : '--'} - - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/GasFeesSummary.tsx b/apps/wallet/src/ui/app/pages/swap/GasFeesSummary.tsx deleted file mode 100644 index 3fc0ad8869b9c..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/GasFeesSummary.tsx +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { getGasSummary, useCoinMetadata, useFormatCoin } from '@mysten/core'; -import { type DryRunTransactionBlockResponse } from '@mysten/sui/client'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMemo } from 'react'; - -interface GasFeesSummaryProps { - transaction?: DryRunTransactionBlockResponse; - feePercentage?: number; - accessFees?: string; - accessFeeType?: string; -} - -export function GasFeesSummary({ - transaction, - feePercentage, - accessFees, - accessFeeType, -}: GasFeesSummaryProps) { - const gasSummary = useMemo(() => { - if (!transaction) return null; - return getGasSummary(transaction); - }, [transaction]); - const totalGas = gasSummary?.totalGas; - const [gasAmount, gasSymbol] = useFormatCoin(totalGas, SUI_TYPE_ARG); - - const { data: accessFeeMetadata } = useCoinMetadata(accessFeeType); - - return ( -
    - - Access Fees ({feePercentage ? `${feePercentage * 100}%` : '--'}) - - } - > - - {accessFees ?? '--'} - {accessFeeMetadata?.symbol ? ` ${accessFeeMetadata.symbol}` : ''} - - - -
    - - - Estimated Gas Fee - - } - > - - {gasAmount ? `${gasAmount} ${gasSymbol}` : '--'} - - -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/MaxSlippage.tsx b/apps/wallet/src/ui/app/pages/swap/MaxSlippage.tsx deleted file mode 100644 index 2881a4de98953..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/MaxSlippage.tsx +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import BottomMenuLayout, { Content, Menu } from '_app/shared/bottom-menu-layout'; -import { Button } from '_app/shared/ButtonUI'; -import { InputWithActionButton } from '_app/shared/InputWithAction'; -import { Text } from '_app/shared/text'; -import { IconTooltip } from '_app/shared/tooltip'; -import Alert from '_components/alert'; -import { IconButton } from '_components/IconButton'; -import Overlay from '_components/overlay'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { type FormValues } from '_pages/swap/constants'; -import { Settings16 } from '@mysten/icons/src'; -import { useFormContext } from 'react-hook-form'; - -const MAX_SLIPPAGE_COPY = - 'Slippage % is the difference between the price you expect to pay or receive for a coin when you initiate a transaction and the actual price at which the transaction is executed.'; - -export function MaxSlippage({ onOpen }: { onOpen: () => void }) { - const { watch } = useFormContext(); - const allowedMaxSlippagePercentage = watch('allowedMaxSlippagePercentage'); - - return ( - - Max Slippage Tolerance -
    - -
    -
    - } - > -
    - - {allowedMaxSlippagePercentage}% - - - } /> -
    - - ); -} - -export function MaxSlippageModal({ isOpen, onClose }: { onClose: () => void; isOpen: boolean }) { - const { - register, - watch, - formState: { errors }, - } = useFormContext(); - - const errorString = errors.allowedMaxSlippagePercentage?.message; - const allowedMaxSlippagePercentage = watch('allowedMaxSlippagePercentage'); - - return ( - -
    - - -
    -
    - - your max slippage tolerance - -
    - - {errorString ? ( -
    - {errorString} -
    - ) : null} -
    - - {MAX_SLIPPAGE_COPY} - -
    -
    -
    - - - -
    -
    -
    - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/constants.ts b/apps/wallet/src/ui/app/pages/swap/constants.ts deleted file mode 100644 index 20b5a224a940f..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/constants.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -export const DEEPBOOK_KEY = 'deepbook'; -export const SUI_CONVERSION_RATE = 6; -export const USDC_CONVERSION_RATE = 9; -export const MAX_FLOAT = 2; -export const WALLET_FEES_PERCENTAGE = 0.5; -export const DEFAULT_WALLET_FEE_ADDRESS = - '0x55b0eb986766351d802ac3e1bbb8750a072b3fa40c782ebe3a0f48c9099f7fd3'; -export const DEFAULT_MAX_SLIPPAGE_PERCENTAGE = '0.5'; -export const SUI_USDC_AVERAGE_CONVERSION_RATE = 3; - -export const initialValues = { - amount: '', - toAssetType: '', - allowedMaxSlippagePercentage: DEFAULT_MAX_SLIPPAGE_PERCENTAGE, -}; -export type FormValues = typeof initialValues; - -export enum Coins { - SUI = 'SUI', - USDC = 'USDC', - USDT = 'USDT', - WETH = 'WETH', - TBTC = 'TBTC', -} diff --git a/apps/wallet/src/ui/app/pages/swap/index.tsx b/apps/wallet/src/ui/app/pages/swap/index.tsx deleted file mode 100644 index a6b040f4d96f9..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/index.tsx +++ /dev/null @@ -1,452 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useActiveAccount } from '_app/hooks/useActiveAccount'; -import { useSigner } from '_app/hooks/useSigner'; -import BottomMenuLayout, { Content, Menu } from '_app/shared/bottom-menu-layout'; -import { Button } from '_app/shared/ButtonUI'; -import { Form } from '_app/shared/forms/Form'; -import { Heading } from '_app/shared/heading'; -import { InputWithActionButton } from '_app/shared/InputWithAction'; -import { Text } from '_app/shared/text'; -import { ButtonOrLink } from '_app/shared/utils/ButtonOrLink'; -import Alert from '_components/alert'; -import LoadingIndicator from '_components/loading/LoadingIndicator'; -import Overlay from '_components/overlay'; -import { parseAmount } from '_helpers'; -import { DescriptionItem } from '_pages/approval-request/transaction-request/DescriptionList'; -import { AssetData } from '_pages/swap/AssetData'; -import { GasFeesSummary } from '_pages/swap/GasFeesSummary'; -import { MaxSlippage, MaxSlippageModal } from '_pages/swap/MaxSlippage'; -import { useSwapTransaction } from '_pages/swap/useSwapTransaction'; -import { - DEFAULT_MAX_SLIPPAGE_PERCENTAGE, - formatSwapQuote, - maxSlippageFormSchema, - useCoinTypesFromRouteParams, - useGetBalance, -} from '_pages/swap/utils'; -import { ampli } from '_shared/analytics/ampli'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { useBalanceInUSD, useCoinMetadata, useZodForm } from '@mysten/core'; -import { useSuiClient } from '@mysten/dapp-kit'; -import { ArrowDown12, ArrowRight16 } from '@mysten/icons'; -import { normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; -import clsx from 'clsx'; -import { useMemo, useState } from 'react'; -import type { SubmitHandler } from 'react-hook-form'; -import { useNavigate, useSearchParams } from 'react-router-dom'; -import { z } from 'zod'; - -export function SwapPage() { - const navigate = useNavigate(); - const client = useSuiClient(); - const queryClient = useQueryClient(); - const activeAccount = useActiveAccount(); - const signer = useSigner(activeAccount); - const [isSlippageModalOpen, setSlippageModalOpen] = useState(false); - const [searchParams] = useSearchParams(); - const currentAddress = activeAccount?.address; - const { fromCoinType, toCoinType } = useCoinTypesFromRouteParams(); - const defaultSlippage = useFeatureValue('defi-max-slippage', DEFAULT_MAX_SLIPPAGE_PERCENTAGE); - const maxSlippage = Number(searchParams.get('maxSlippage') || defaultSlippage); - const presetAmount = searchParams.get('presetAmount'); - const isSui = fromCoinType - ? normalizeStructTag(fromCoinType) === normalizeStructTag(SUI_TYPE_ARG) - : false; - const { data: fromCoinData } = useCoinMetadata(fromCoinType); - - const validationSchema = useMemo(() => { - return z - .object({ - amount: z - .number({ - coerce: true, - invalid_type_error: 'Input must be number only', - }) - .pipe(z.coerce.string()), - }) - .merge(maxSlippageFormSchema) - .superRefine(async ({ amount }, ctx) => { - if (!fromCoinType) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'Select a coin to swap from', - }); - return z.NEVER; - } - - const { totalBalance } = await client.getBalance({ - owner: currentAddress || '', - coinType: fromCoinType, - }); - const data = await client.getCoinMetadata({ coinType: fromCoinType }); - const bnAmount = new BigNumber(amount); - const bnMaxBalance = new BigNumber(totalBalance || 0).shiftedBy(-1 * (data?.decimals ?? 0)); - - if (bnAmount.isGreaterThan(bnMaxBalance)) { - ctx.addIssue({ - path: ['amount'], - code: z.ZodIssueCode.custom, - message: 'Insufficient balance', - }); - return z.NEVER; - } - - if (!toCoinType) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'Select a coin to swap to', - }); - return z.NEVER; - } - - if (!bnAmount.isFinite() || !bnAmount.isPositive()) { - ctx.addIssue({ - path: ['amount'], - code: z.ZodIssueCode.custom, - message: 'Expected a valid number', - }); - return z.NEVER; - } - if (!bnAmount.gt(0)) { - ctx.addIssue({ - path: ['amount'], - code: z.ZodIssueCode.custom, - message: 'Value must be greater than 0', - }); - return z.NEVER; - } - if (!fromCoinType || !toCoinType) { - return z.NEVER; - } - }); - }, [client, currentAddress, fromCoinType, toCoinType]); - - type FormType = z.infer; - - const form = useZodForm({ - mode: 'all', - schema: validationSchema, - defaultValues: { - allowedMaxSlippagePercentage: maxSlippage, - amount: presetAmount || '', - }, - }); - - const { - watch, - setValue, - handleSubmit, - register, - reset, - formState: { isValid: isFormValid, isSubmitting, errors }, - } = form; - - const [allowedMaxSlippagePercentage, amount] = watch(['allowedMaxSlippagePercentage', 'amount']); - - const { data: balance } = useGetBalance({ - coinType: fromCoinType!, - owner: currentAddress, - }); - - const GAS_RESERVE = 0.1; - const maxBalance = useMemo(() => { - const bnBalance = new BigNumber(balance?.totalBalance || 0).shiftedBy( - -1 * (fromCoinData?.decimals ?? 0), - ); - return isSui && bnBalance.gt(GAS_RESERVE) - ? bnBalance - .minus(GAS_RESERVE) - .decimalPlaces(fromCoinData?.decimals ?? 0) - .toString() - : bnBalance.decimalPlaces(fromCoinData?.decimals ?? 0).toString(); - }, [balance?.totalBalance, fromCoinData?.decimals, isSui]); - - const { data: toCoinData } = useCoinMetadata(toCoinType); - const fromCoinSymbol = fromCoinData?.symbol; - const toCoinSymbol = toCoinData?.symbol; - - const parsed = parseAmount(amount || '0', fromCoinData?.decimals || 0); - const isMaxBalance = new BigNumber(amount).isEqualTo(new BigNumber(maxBalance)); - const { - data, - isPending: swapTransactionPending, - isLoading: swapTransactionLoading, - refetch, - error, - } = useSwapTransaction({ - sender: currentAddress, - fromType: fromCoinType || '', - toType: toCoinType || '', - amount: parsed.toString(), - slippage: Number(allowedMaxSlippagePercentage), - enabled: isFormValid && parsed > 0n && !!fromCoinType && !!toCoinType, - source: 'sui-wallet', - }); - - const swapData = useMemo(() => { - if (!data) return null; - return formatSwapQuote({ - result: data, - sender: currentAddress || '', - fromType: fromCoinType || '', - toType: toCoinType || '', - fromCoinDecimals: fromCoinData?.decimals ?? 0, - toCoinDecimals: toCoinData?.decimals ?? 0, - }); - }, [currentAddress, fromCoinType, toCoinType, fromCoinData, toCoinData, data]); - - const toCoinBalanceInUSD = useBalanceInUSD(toCoinType || '', swapData?.toAmount ?? 0n); - const inputAmountInUSD = useBalanceInUSD(fromCoinType || '', parsed || 0n); - - const { mutate: handleSwap, isPending: handleSwapPending } = useMutation({ - mutationFn: async (formData: FormType) => { - const txn = swapData?.transaction; - return signer!.signAndExecuteTransactionBlock({ - transactionBlock: txn!, - options: { - showInput: true, - showEffects: true, - showEvents: true, - }, - }); - }, - onSuccess: (response) => { - queryClient.invalidateQueries({ queryKey: ['get-coins'] }); - queryClient.invalidateQueries({ queryKey: ['coin-balance'] }); - - ampli.swappedCoin({ - fromCoinType: fromCoinType || '', - toCoinType: toCoinType || '', - totalBalance: Number(amount), - estimatedReturnBalance: inputAmountInUSD || 0, - provider: swapData?.provider, - }); - - const receiptUrl = `/receipt?txdigest=${encodeURIComponent( - response.digest, - )}&from=transactions`; - return navigate(receiptUrl); - }, - onError: (error) => { - ampli.swappedCoinFailed({ - estimatedReturnBalance: Number(swapData?.formattedToAmount || 0), - fromCoinType: fromCoinType!, - toCoinType: toCoinType!, - totalBalance: Number(amount || 0), - errorMessage: error.message, - provider: swapData?.provider, - }); - }, - }); - - const handleOnsubmit: SubmitHandler = (formData) => { - handleSwap(formData); - }; - - const showGasFeeBanner = !swapTransactionPending && swapData && isSui && isMaxBalance; - - return ( - navigate('/')}> -
    - - -
    -
    - -
    - - {isMaxBalance ? '~ ' : ''}$ - {new BigNumber(inputAmountInUSD || 0).toFixed(2)} - - ) - } - onActionClicked={() => { - setValue('amount', maxBalance, { shouldValidate: true }); - }} - /> -
    - {showGasFeeBanner && ( - - - {GAS_RESERVE} {fromCoinSymbol} has been set aside to cover estimated max gas - fees for this transaction - - - )} -
    - - { - navigate( - `/swap?${new URLSearchParams({ - type: toCoinType || '', - toType: fromCoinType || '', - }).toString()}`, - ); - reset(); - }} - > -
    -
    - -
    -
    - - -
    -
    - -
    - {swapTransactionLoading ? ( -
    - - - Calculating... - -
    - ) : ( -
    - - {swapData?.formattedToAmount ?? 0} - - - {toCoinSymbol} - -
    - - ${new BigNumber(toCoinBalanceInUSD || 0).toFixed(2)} - -
    -
    - )} -
    - -
    - setSlippageModalOpen(true)} /> -
    - { - navigate( - `/swap?${new URLSearchParams({ - type: fromCoinType || '', - toType: toCoinType || '', - maxSlippage: allowedMaxSlippagePercentage.toString(), - }).toString()}`, - ); - setSlippageModalOpen(false); - }} - /> - - {error && ( -
    - - - Calculation failed - - - {error.message || 'An error has occurred, try again.'} - - -
    - )} -
    - - {swapData?.estimatedRate && ( -
    - Estimated Rate}> - - 1 {fromCoinSymbol} ≈ {swapData?.estimatedRate} {toCoinSymbol} - - -
    - )} - - -
    - - - - - - -
    - - ); -} diff --git a/apps/wallet/src/ui/app/pages/swap/useSwapTransaction.ts b/apps/wallet/src/ui/app/pages/swap/useSwapTransaction.ts deleted file mode 100644 index b3cdf46d97c8e..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/useSwapTransaction.ts +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useSuiClient } from '@mysten/dapp-kit'; -import { type DryRunTransactionBlockResponse } from '@mysten/sui/client'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; - -export type SwapRequest = { - amount: string; - fromType?: string; - slippage: number; - source: string; - sender?: string; - toType?: string; -}; - -export type SwapResponse = { - bytes: string; - error: string; - fee: { - percentage: number; - address: string; - }; - outAmount: string; - provider: string; -}; - -export type SwapResult = - | (SwapResponse & { - dryRunResponse: DryRunTransactionBlockResponse; - }) - | null; - -const getQueryKey = (params: SwapRequest) => ['swap', params]; - -async function* streamAsyncIterator(stream: ReadableStream): AsyncGenerator { - const reader = stream.getReader(); - const decoder = new TextDecoder('utf-8'); - let buffer = ''; - - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - buffer += decoder.decode(value, { stream: true }); - const lines = buffer.split('\n'); - buffer = lines.pop() || ''; - - for (const line of lines) { - if (line.trim()) { - yield JSON.parse(line.trim()); - } - } - } - } finally { - reader.releaseLock(); - } -} - -export function useSwapTransaction({ enabled, ...params }: SwapRequest & { enabled: boolean }) { - const client = useSuiClient(); - const queryClient = useQueryClient(); - - return useQuery({ - queryKey: getQueryKey(params), - queryFn: async ({ signal }) => { - const response = await fetch('https://apps-backend.sui.io/swap', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(params), - signal, - }); - - if (!response.body || !response.ok) { - throw new Error(`Failed to fetch swap data ${response.statusText}`); - } - - for await (const swapResponse of streamAsyncIterator(response.body)) { - if (!swapResponse) continue; - if (swapResponse.error) throw new Error(swapResponse.error); - - const dryRunResponse = await client.dryRunTransactionBlock({ - transactionBlock: swapResponse.bytes, - }); - - queryClient.setQueryData(getQueryKey(params), { - dryRunResponse, - ...swapResponse, - }); - } - - return queryClient.getQueryData(getQueryKey(params)) ?? null; - }, - staleTime: 0, - enabled: enabled && !!params.amount && !!params.sender && !!params.fromType && !!params.toType, - }); -} diff --git a/apps/wallet/src/ui/app/pages/swap/utils.ts b/apps/wallet/src/ui/app/pages/swap/utils.ts deleted file mode 100644 index 676fd3148795c..0000000000000 --- a/apps/wallet/src/ui/app/pages/swap/utils.ts +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -import { useActiveAccount } from '_app/hooks/useActiveAccount'; -import { useCoinsReFetchingConfig } from '_hooks'; -import { type SwapResult } from '_pages/swap/useSwapTransaction'; -import { useFeatureValue } from '@growthbook/growthbook-react'; -import { - CoinFormat, - formatBalance, - getBalanceChangeSummary, - getOwnerAddress, - roundFloat, - useCoinMetadata, - useFormatCoin, -} from '@mysten/core'; -import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { type TransactionEffects } from '@mysten/sui/client'; -import { Transaction } from '@mysten/sui/transactions'; -import { normalizeStructTag, SUI_DECIMALS, SUI_TYPE_ARG } from '@mysten/sui/utils'; -import BigNumber from 'bignumber.js'; -import { useSearchParams } from 'react-router-dom'; -import { z } from 'zod'; - -export const DEFAULT_MAX_SLIPPAGE_PERCENTAGE = 1; - -export const W_USDC_TYPE_ARG = - '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN'; -export const USDC_TYPE_ARG = - '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC'; - -export function useSwapData({ - baseCoinType, - quoteCoinType, -}: { - baseCoinType: string; - quoteCoinType: string; -}) { - const activeAccount = useActiveAccount(); - const activeAccountAddress = activeAccount?.address; - const { staleTime, refetchInterval } = useCoinsReFetchingConfig(); - - const { data: baseCoinBalanceData, isPending: baseCoinBalanceDataLoading } = useSuiClientQuery( - 'getBalance', - { coinType: baseCoinType, owner: activeAccountAddress! }, - { enabled: !!activeAccountAddress, refetchInterval, staleTime }, - ); - - const { data: quoteCoinBalanceData, isPending: quoteCoinBalanceDataLoading } = useSuiClientQuery( - 'getBalance', - { coinType: quoteCoinType, owner: activeAccountAddress! }, - { enabled: !!activeAccountAddress, refetchInterval, staleTime }, - ); - - const rawBaseBalance = baseCoinBalanceData?.totalBalance; - const rawQuoteBalance = quoteCoinBalanceData?.totalBalance; - - const [formattedBaseBalance, baseCoinSymbol, baseCoinMetadata] = useFormatCoin( - rawBaseBalance, - baseCoinType, - ); - const [formattedQuoteBalance, quoteCoinSymbol, quoteCoinMetadata] = useFormatCoin( - rawQuoteBalance, - quoteCoinType, - ); - - return { - baseCoinBalanceData, - quoteCoinBalanceData, - formattedBaseBalance, - formattedQuoteBalance, - baseCoinSymbol, - quoteCoinSymbol, - baseCoinMetadata, - quoteCoinMetadata, - isPending: baseCoinBalanceDataLoading || quoteCoinBalanceDataLoading, - }; -} - -export function getUSDCurrency(amount?: number | null) { - if (typeof amount !== 'number') { - return null; - } - - return roundFloat(amount, 4).toLocaleString('en', { - style: 'currency', - currency: 'USD', - }); -} - -export const maxSlippageFormSchema = z.object({ - allowedMaxSlippagePercentage: z - .number({ - coerce: true, - invalid_type_error: 'Input must be number only', - }) - .positive() - .max(100, 'Value must be between 0 and 100'), -}); - -export function useCoinTypesFromRouteParams() { - const [searchParams] = useSearchParams(); - const fromCoinType = searchParams.get('type'); - const toCoinType = searchParams.get('toType'); - - // Both are already defined, just use them: - if (fromCoinType && toCoinType) { - return { fromCoinType, toCoinType }; - } - - // Neither is set, default to SUI -> USDC - if (!fromCoinType && !toCoinType) { - return { fromCoinType: SUI_TYPE_ARG, toCoinType: USDC_TYPE_ARG }; - } - - return { fromCoinType, toCoinType }; -} - -export function useGetBalance({ coinType, owner }: { coinType?: string; owner?: string }) { - const { data: coinMetadata } = useCoinMetadata(coinType); - const refetchInterval = useFeatureValue('wallet-balance-refetch-interval', 20_000); - - return useSuiClientQuery( - 'getBalance', - { - coinType, - owner: owner!, - }, - { - select: (data) => { - const formatted = formatBalance( - data.totalBalance, - coinMetadata?.decimals ?? 0, - CoinFormat.ROUNDED, - ); - - return { - ...data, - formatted, - }; - }, - refetchInterval, - staleTime: 5_000, - enabled: !!owner && !!coinType, - }, - ); -} - -export const getTotalGasCost = (effects: TransactionEffects) => { - return ( - BigInt(effects.gasUsed.computationCost) + - BigInt(effects.gasUsed.storageCost) - - BigInt(effects.gasUsed.storageRebate) - ); -}; - -export function formatSwapQuote({ - result, - sender, - fromType, - toType, - fromCoinDecimals, - toCoinDecimals, -}: { - fromCoinDecimals: number; - fromType?: string; - result: SwapResult; - sender: string; - toCoinDecimals: number; - toType?: string; -}) { - if (!result || !fromType || !toType) return null; - - const { dryRunResponse, fee } = result; - const { balanceChanges } = dryRunResponse; - const summary = getBalanceChangeSummary(dryRunResponse, []); - const fromAmount = - summary?.[sender]?.find( - (bc) => normalizeStructTag(bc.coinType) === normalizeStructTag(fromType), - )?.amount ?? 0n; - const toAmount = - summary?.[sender]?.find((bc) => normalizeStructTag(bc.coinType) === normalizeStructTag(toType)) - ?.amount ?? 0n; - - const formattedToAmount = formatBalance(toAmount, toCoinDecimals); - - const estimatedRate = new BigNumber(toAmount.toString()) - .shiftedBy(fromCoinDecimals - toCoinDecimals) - .dividedBy(new BigNumber(fromAmount.toString()).abs()) - .toFormat(toCoinDecimals); - - const accessFeeBalanceChange = balanceChanges.find( - (bc) => ![fee.address, sender].includes(getOwnerAddress(bc.owner)), - ); - - const accessFees = new BigNumber((accessFeeBalanceChange?.amount || 0n).toString()).shiftedBy( - -toCoinDecimals, - ); - const coinOut = new BigNumber(toAmount.toString()).shiftedBy(-toCoinDecimals); - const accessFeePercentage = accessFees.dividedBy(coinOut).multipliedBy(100).toFormat(3); - - const estimatedToAmount = new BigNumber(toAmount.toString()) - .shiftedBy(-toCoinDecimals) - .minus(accessFees) - .toFormat(toCoinDecimals); - - const gas = formatBalance(getTotalGasCost(dryRunResponse.effects), SUI_DECIMALS); - - return { - provider: result?.provider, - dryRunResponse, - transaction: Transaction.from(result.bytes), - estimatedRate, - formattedToAmount, - accessFeePercentage, - accessFees: accessFees.toFormat(toCoinDecimals), - accessFeeType: accessFeeBalanceChange?.coinType, - estimatedToAmount, - estimatedGas: gas, - toAmount: toAmount.toString(), - feePercentage: fee.percentage, - }; -} diff --git a/apps/wallet/src/ui/app/redux/RootReducer.ts b/apps/wallet/src/ui/app/redux/RootReducer.ts deleted file mode 100644 index 1ddc27d915fb9..0000000000000 --- a/apps/wallet/src/ui/app/redux/RootReducer.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { combineReducers } from '@reduxjs/toolkit'; - -import app from './slices/app'; -import permissions from './slices/permissions'; -import transactionRequests from './slices/transaction-requests'; - -const rootReducer = combineReducers({ - app, - permissions, - transactionRequests, -}); - -export type RootState = ReturnType; - -export default rootReducer; diff --git a/apps/wallet/src/ui/app/redux/slices/app/AppType.ts b/apps/wallet/src/ui/app/redux/slices/app/AppType.ts deleted file mode 100644 index 65d796a3ba52a..0000000000000 --- a/apps/wallet/src/ui/app/redux/slices/app/AppType.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -export enum AppType { - unknown, - fullscreen, - popup, -} - -export function getFromLocationSearch(search: string) { - if (/type=popup/.test(window.location.search)) { - return AppType.popup; - } - return AppType.fullscreen; -} diff --git a/apps/wallet/src/ui/app/redux/slices/app/index.ts b/apps/wallet/src/ui/app/redux/slices/app/index.ts deleted file mode 100644 index 1800532d8c19a..0000000000000 --- a/apps/wallet/src/ui/app/redux/slices/app/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { DEFAULT_API_ENV, walletApiProvider } from '_app/ApiProvider'; -import type { RootState } from '_redux/RootReducer'; -import type { API_ENV, NetworkEnvType } from '_src/shared/api-env'; -import type { AppThunkConfig } from '_store/thunk-extras'; -import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; -import type { PayloadAction } from '@reduxjs/toolkit'; - -import { AppType } from './AppType'; - -type AppState = { - appType: AppType; - apiEnv: API_ENV; - navVisible: boolean; - customRPC?: string | null; - activeOrigin: string | null; - activeOriginFavIcon: string | null; -}; - -const initialState: AppState = { - appType: AppType.unknown, - apiEnv: DEFAULT_API_ENV, - customRPC: null, - navVisible: true, - activeOrigin: null, - activeOriginFavIcon: null, -}; - -export const changeActiveNetwork = createAsyncThunk< - void, - { network: NetworkEnvType; store?: boolean }, - AppThunkConfig ->('changeRPCNetwork', async ({ network, store = false }, { extra: { background }, dispatch }) => { - if (store) { - await background.setActiveNetworkEnv(network); - } - walletApiProvider.setNewJsonRpcProvider(network.env, network.customRpcUrl); - await dispatch(slice.actions.setActiveNetwork(network)); -}); - -const slice = createSlice({ - name: 'app', - reducers: { - initAppType: (state, { payload }: PayloadAction) => { - state.appType = payload; - }, - setActiveNetwork: ( - state, - { payload: { env, customRpcUrl } }: PayloadAction, - ) => { - state.apiEnv = env; - state.customRPC = customRpcUrl; - }, - setNavVisibility: (state, { payload: isVisible }: PayloadAction) => { - state.navVisible = isVisible; - }, - setActiveOrigin: ( - state, - { payload }: PayloadAction<{ origin: string | null; favIcon: string | null }>, - ) => { - state.activeOrigin = payload.origin; - state.activeOriginFavIcon = payload.favIcon; - }, - }, - initialState, -}); - -export const { initAppType, setNavVisibility, setActiveOrigin } = slice.actions; -export const getNavIsVisible = ({ app }: RootState) => app.navVisible; - -export default slice.reducer; diff --git a/apps/wallet/src/ui/app/redux/slices/permissions/index.ts b/apps/wallet/src/ui/app/redux/slices/permissions/index.ts deleted file mode 100644 index 9940a06e80ec4..0000000000000 --- a/apps/wallet/src/ui/app/redux/slices/permissions/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Permission } from '_messages/payloads/permissions'; -import type { RootState } from '_redux/RootReducer'; -import type { AppThunkConfig } from '_store/thunk-extras'; -import { - createAsyncThunk, - createEntityAdapter, - createSelector, - createSlice, -} from '@reduxjs/toolkit'; -import type { PayloadAction } from '@reduxjs/toolkit'; - -const permissionsAdapter = createEntityAdapter({ - sortComparer: (a, b) => { - const aDate = new Date(a.createdDate); - const bDate = new Date(b.createdDate); - return aDate.getTime() - bDate.getTime(); - }, -}); - -export const respondToPermissionRequest = createAsyncThunk< - { - id: string; - accounts: string[]; - allowed: boolean; - responseDate: string; - }, - { id: string; accounts: string[]; allowed: boolean }, - AppThunkConfig ->('respond-to-permission-request', ({ id, accounts, allowed }, { extra: { background } }) => { - const responseDate = new Date().toISOString(); - background.sendPermissionResponse(id, accounts, allowed, responseDate); - return { id, accounts, allowed, responseDate }; -}); - -const slice = createSlice({ - name: 'permissions', - initialState: permissionsAdapter.getInitialState({ initialized: false }), - reducers: { - setPermissions: (state, { payload }: PayloadAction) => { - permissionsAdapter.setAll(state, payload); - state.initialized = true; - }, - }, - extraReducers: (build) => { - build.addCase(respondToPermissionRequest.fulfilled, (state, { payload }) => { - const { id, accounts, allowed, responseDate } = payload; - permissionsAdapter.updateOne(state, { - id, - changes: { - accounts, - allowed, - responseDate, - }, - }); - }); - }, -}); - -export default slice.reducer; - -export const { setPermissions } = slice.actions; - -export const permissionsSelectors = permissionsAdapter.getSelectors( - (state: RootState) => state.permissions, -); - -export function createDappStatusSelector(origin: string | null, activeAddress: string | null) { - if (!origin || !activeAddress) { - return () => false; - } - return createSelector(permissionsSelectors.selectAll, (permissions) => { - const originPermission = permissions.find((aPermission) => aPermission.origin === origin); - if (!originPermission) { - return false; - } - return ( - originPermission.allowed && activeAddress && originPermission.accounts.includes(activeAddress) - ); - }); -} diff --git a/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts b/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts deleted file mode 100644 index a84da3a45428b..0000000000000 --- a/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { SuiMoveObject, SuiObjectData } from '@mysten/sui/client'; - -const COIN_TYPE = '0x2::coin::Coin'; -const COIN_TYPE_ARG_REGEX = /^0x2::coin::Coin<(.+)>$/; - -export const GAS_TYPE_ARG = '0x2::sui::SUI'; -export const GAS_SYMBOL = 'SUI'; - -// TODO use sdk -export class Coin { - public static isCoin(obj: SuiObjectData) { - const type = obj?.content?.dataType === 'package' ? 'package' : obj?.content?.type; - return type?.startsWith(COIN_TYPE) ?? false; - } - - public static getCoinTypeArg(obj: SuiMoveObject) { - const res = obj.type.match(COIN_TYPE_ARG_REGEX); - return res ? res[1] : null; - } - - public static isSUI(obj: SuiMoveObject) { - const arg = Coin.getCoinTypeArg(obj); - return arg ? Coin.getCoinSymbol(arg) === 'SUI' : false; - } - - public static getCoinSymbol(coinTypeArg: string) { - return coinTypeArg.substring(coinTypeArg.lastIndexOf(':') + 1); - } - - public static getBalance(obj: SuiMoveObject): bigint { - return BigInt((obj.fields as { balance: string }).balance); - } - - public static getID(obj: SuiMoveObject): string { - return (obj.fields as { id: { id: string } }).id.id; - } - - public static getCoinTypeFromArg(coinTypeArg: string) { - return `${COIN_TYPE}<${coinTypeArg}>`; - } -} diff --git a/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts b/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts deleted file mode 100644 index a1c50666bc480..0000000000000 --- a/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { ApprovalRequest } from '_payloads/transactions/ApprovalRequest'; -import type { RootState } from '_redux/RootReducer'; -import { getSignerOperationErrorMessage } from '_src/ui/app/helpers/errorMessages'; -import { - type SignedMessage, - type SignedTransaction, - type WalletSigner, -} from '_src/ui/app/WalletSigner'; -import type { AppThunkConfig } from '_store/thunk-extras'; -import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; -import { Transaction } from '@mysten/sui/transactions'; -import { fromBase64 } from '@mysten/sui/utils'; -import { createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; -import type { PayloadAction } from '@reduxjs/toolkit'; - -const txRequestsAdapter = createEntityAdapter({ - sortComparer: (a, b) => { - const aDate = new Date(a.createdDate); - const bDate = new Date(b.createdDate); - return aDate.getTime() - bDate.getTime(); - }, -}); - -export const respondToTransactionRequest = createAsyncThunk< - { - txRequestID: string; - approved: boolean; - txResponse: SuiTransactionBlockResponse | null; - }, - { - txRequestID: string; - approved: boolean; - signer: WalletSigner; - clientIdentifier?: string; - }, - AppThunkConfig ->( - 'respond-to-transaction-request', - async ( - { txRequestID, approved, signer, clientIdentifier }, - { extra: { background }, getState }, - ) => { - const state = getState(); - const txRequest = txRequestsSelectors.selectById(state, txRequestID); - if (!txRequest) { - throw new Error(`TransactionRequest ${txRequestID} not found`); - } - let txSigned: SignedTransaction | undefined = undefined; - let txResult: SuiTransactionBlockResponse | SignedMessage | undefined = undefined; - let txResultError: string | undefined; - if (approved) { - try { - if (txRequest.tx.type === 'sign-message') { - txResult = await signer.signMessage( - { - message: fromBase64(txRequest.tx.message), - }, - clientIdentifier, - ); - } else if (txRequest.tx.type === 'transaction') { - const tx = Transaction.from(txRequest.tx.data); - if (txRequest.tx.justSign) { - // Just a signing request, do not submit - txSigned = await signer.signTransactionBlock( - { - transactionBlock: tx, - }, - clientIdentifier, - ); - } else { - txResult = await signer.signAndExecuteTransactionBlock( - { - transactionBlock: tx, - options: txRequest.tx.options, - requestType: txRequest.tx.requestType, - }, - clientIdentifier, - ); - } - } else { - throw new Error( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - `Unexpected type: ${(txRequest.tx as any).type}`, - ); - } - } catch (error) { - txResultError = getSignerOperationErrorMessage(error); - } - } - background.sendTransactionRequestResponse( - txRequestID, - approved, - txResult, - txResultError, - txSigned, - ); - return { txRequestID, approved: approved, txResponse: null }; - }, -); - -const slice = createSlice({ - name: 'transaction-requests', - initialState: txRequestsAdapter.getInitialState({ - initialized: false, - }), - reducers: { - setTransactionRequests: (state, { payload }: PayloadAction) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - txRequestsAdapter.setAll(state, payload); - state.initialized = true; - }, - }, - extraReducers: (build) => { - build.addCase(respondToTransactionRequest.fulfilled, (state, { payload }) => { - const { txRequestID, approved: allowed, txResponse } = payload; - txRequestsAdapter.updateOne(state, { - id: txRequestID, - changes: { - approved: allowed, - txResult: txResponse || undefined, - }, - }); - }); - }, -}); - -export default slice.reducer; - -export const { setTransactionRequests } = slice.actions; - -export const txRequestsSelectors = txRequestsAdapter.getSelectors( - (state: RootState) => state.transactionRequests, -); diff --git a/apps/wallet/src/ui/app/redux/store/index.ts b/apps/wallet/src/ui/app/redux/store/index.ts deleted file mode 100644 index 27a3efd462ef2..0000000000000 --- a/apps/wallet/src/ui/app/redux/store/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import rootReducer from '_redux/RootReducer'; -import { configureStore } from '@reduxjs/toolkit'; - -import { thunkExtras } from './thunk-extras'; - -const store = configureStore({ - reducer: rootReducer, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware({ - thunk: { - extraArgument: thunkExtras, - }, - }), -}); - -export default store; - -export type AppDispatch = typeof store.dispatch; diff --git a/apps/wallet/src/ui/app/redux/store/thunk-extras.ts b/apps/wallet/src/ui/app/redux/store/thunk-extras.ts deleted file mode 100644 index 0c82a7ddd66b6..0000000000000 --- a/apps/wallet/src/ui/app/redux/store/thunk-extras.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { BackgroundClient } from '_app/background-client'; -import { growthbook } from '_app/experimentation/feature-gating'; -import type { RootState } from '_redux/RootReducer'; -import type { AppDispatch } from '_store'; - -export const thunkExtras = { - growthbook, - background: new BackgroundClient(), -}; - -type ThunkExtras = typeof thunkExtras; - -export interface AppThunkConfig { - extra: ThunkExtras; - state: RootState; - dispatch: AppDispatch; -} diff --git a/apps/wallet/src/ui/app/shared/Badge.stories.tsx b/apps/wallet/src/ui/app/shared/Badge.stories.tsx deleted file mode 100644 index 1359556bffe18..0000000000000 --- a/apps/wallet/src/ui/app/shared/Badge.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Meta, type StoryObj } from '@storybook/react'; - -import { Badge } from './Badge'; - -export default { - component: Badge, -} as Meta; - -export const Success: StoryObj = { - args: { - label: 'New', - variant: 'success', - }, -}; - -export const Warning: StoryObj = { - args: { - label: 'At Risk', - variant: 'warning', - }, -}; diff --git a/apps/wallet/src/ui/app/shared/Badge.tsx b/apps/wallet/src/ui/app/shared/Badge.tsx deleted file mode 100644 index beba54cbd3cd1..0000000000000 --- a/apps/wallet/src/ui/app/shared/Badge.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; - -const badgeStyle = cva( - [ - 'text-captionSmallExtra flex uppercase font-medium px-1 py-0.5 rounded w-fit-content h-3.5 w-max justify-center items-center', - ], - { - variants: { - variant: { - warning: 'bg-issue-light text-issue-dark', - success: 'bg-sui/30 text-hero-dark', - }, - }, - }, -); - -export interface BadgeProps extends VariantProps { - label: string; -} - -export function Badge({ label, ...styles }: BadgeProps) { - return
    {label}
    ; -} diff --git a/apps/wallet/src/ui/app/shared/ButtonConnectedTo.stories.tsx b/apps/wallet/src/ui/app/shared/ButtonConnectedTo.stories.tsx deleted file mode 100644 index e337f44f5ef04..0000000000000 --- a/apps/wallet/src/ui/app/shared/ButtonConnectedTo.stories.tsx +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { StakeAdd16 } from '@mysten/icons'; -import { type Meta, type StoryObj } from '@storybook/react'; - -import { ButtonConnectedTo } from './ButtonConnectedTo'; - -export default { - component: ButtonConnectedTo, -} as Meta; - -export const Default: StoryObj = { - args: { - text: 'Button', - }, -}; - -export const LightGrey: StoryObj = { - args: { - text: 'Button', - bgOnHover: 'grey', - }, -}; - -export const Disabled: StoryObj = { - args: { - text: 'Button', - bgOnHover: 'grey', - disabled: true, - }, -}; - -export const LongText: StoryObj = { - render: (props) => { - return ( -
    - -
    - ); - }, - args: { - text: 'Button with very long text', - bgOnHover: 'grey', - iconBefore: , - iconAfter: , - }, -}; diff --git a/apps/wallet/src/ui/app/shared/ButtonConnectedTo.tsx b/apps/wallet/src/ui/app/shared/ButtonConnectedTo.tsx deleted file mode 100644 index 9a42724cc190a..0000000000000 --- a/apps/wallet/src/ui/app/shared/ButtonConnectedTo.tsx +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, cx, type VariantProps } from 'class-variance-authority'; -import clsx from 'clsx'; -import { forwardRef, type ComponentProps, type ReactNode } from 'react'; - -const styles = cva( - [ - 'cursor-pointer outline-0 flex flex-row items-center py-1 px-2 gap-1 rounded-2xl', - 'transition text-body-small font-medium border border-solid w-full min-w-0', - 'border-1 border-gray-45 bg-transparent group', - 'hover:text-hero hover:bg-sui-light hover:border-sui', - 'focus:text-hero focus:bg-sui-light focus:border-sui', - 'active:text-steel active:bg-gray-45 active:border-transparent', - 'disabled:text-gray-60 disabled:bg-transparent disabled:border-transparent', - ], - { - variants: { - bgOnHover: { - blueLight: ['text-hero'], - grey: ['text-steel-dark'], - }, - }, - defaultVariants: { - bgOnHover: 'blueLight', - }, - }, -); - -export interface ButtonConnectedToProps - extends VariantProps, - Omit, 'ref' | 'className'> { - iconBefore?: ReactNode; - text?: ReactNode; - iconAfter?: ReactNode; - truncate?: boolean; -} - -export const ButtonConnectedTo = forwardRef( - ({ bgOnHover, iconBefore, iconAfter, text, truncate, ...rest }, ref) => { - return ( - - ); - }, -); diff --git a/apps/wallet/src/ui/app/shared/ButtonUI.stories.tsx b/apps/wallet/src/ui/app/shared/ButtonUI.stories.tsx deleted file mode 100644 index 99b562a28d0a9..0000000000000 --- a/apps/wallet/src/ui/app/shared/ButtonUI.stories.tsx +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Add16, StakeAdd16 } from '@mysten/icons'; -import { type Meta, type StoryObj } from '@storybook/react'; - -import { Button } from './ButtonUI'; - -export default { - component: Button, -} as Meta; - -export const Default: StoryObj = { - args: { - text: 'Default Button', - }, -}; - -export const AllButton: StoryObj = { - render: (props) => { - const variants = [ - 'primary', - 'secondary', - 'outline', - 'outlineWarning', - 'warning', - 'plain', - ] as const; - const sizes = ['tall', 'narrow', 'xs'] as const; - return ( -
    - {sizes.map((size) => - variants.map((variant) => ( -
    -
    {`${variant}-${size}`}
    -
    - )), - )} -
    - ); - }, -}; - -export const AllLink: StoryObj = { - ...AllButton, - args: { to: '.' }, -}; -export const AllAnchor: StoryObj = { - ...AllButton, - args: { href: 'https://example.com' }, -}; diff --git a/apps/wallet/src/ui/app/shared/ButtonUI.tsx b/apps/wallet/src/ui/app/shared/ButtonUI.tsx deleted file mode 100644 index 9a8d0b9e4edf1..0000000000000 --- a/apps/wallet/src/ui/app/shared/ButtonUI.tsx +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -// TODO: replace all the existing button usages (the current Button component or button) with this -// TODO: rename this to Button when the existing Button component is removed - -import { cva, type VariantProps } from 'class-variance-authority'; -import { forwardRef, type ReactNode, type Ref } from 'react'; - -import { ButtonOrLink, type ButtonOrLinkProps } from './utils/ButtonOrLink'; - -const styles = cva( - [ - 'transition no-underline outline-none group', - 'flex flex-row flex-nowrap items-center justify-center gap-2', - 'cursor-pointer text-body font-semibold max-w-full min-w-0 w-full', - ], - { - variants: { - variant: { - primary: [ - 'bg-hero-dark text-white border-none', - 'hover:bg-hero focus:bg-hero', - 'visited:text-white', - 'active:text-white/70', - 'disabled:bg-hero-darkest disabled:text-white disabled:opacity-40', - ], - secondary: [ - 'bg-hero-darkest/10 text-steel-dark border-none', - 'hover:bg-hero-darkest/20 hover:text-steel-darker', - 'focus:bg-hero-darkest/10 focus:text-steel-dark/70', - 'active:text-steel-dark/70', - 'visited:text-steel-darkest', - 'disabled:bg-hero-darkest/5 disabled:text-steel/50', - ], - secondarySui: [ - 'bg-transparent text-steel border-none', - 'hover:bg-sui-light focus:bg-sui-light', - 'visited:text-steel-darker', - 'active:text-steel-dark/70', - 'disabled:bg-gray-40 disabled:text-steel/50', - ], - outline: [ - 'bg-white border-solid border border-steel text-steel-dark text-body font-semibold', - 'hover:border-steel-dark focus:border-steel-dark hover:text-steel-darker focus:text-steel-darker', - 'visited:text-steel-dark', - 'active:border-steel active:text-steel-dark', - 'disabled:border-gray-45 disabled:text-gray-60', - ], - outlineWarning: [ - 'bg-white border-solid border border-steel text-issue-dark', - 'hover:border-steel-dark focus:border-steel-dark', - 'visited:text-issue-dark', - 'active:border-steel active:text-issue/70', - 'disabled:border-gray-45 disabled:text-issue-dark/50', - ], - warning: [ - 'bg-issue-light text-issue-dark border-none', - 'visited:text-issue-dark', - 'active:text-issue/70', - 'disabled:opacity-40 disabled:text-issue-dark/50', - ], - plain: [ - 'bg-transparent text-steel-darker border-none', - 'visited:text-steel-darker', - 'active:text-steel-darker/70', - 'disabled:text-steel-dark/50', - ], - hidden: [ - 'bg-gray-45 bg-opacity-25 text-gray-60 hover:text-sui-dark hover:bg-gray-35 hover:bg-opacity-75 border-none h-full w-full backdrop-blur-md', - ], - }, - size: { - tall: ['h-10 px-5 rounded-xl'], - narrow: ['h-9 py-2.5 px-5 rounded-lg'], - xs: ['h-6 rounded-lg px-2 py-3 !uppercase text-captionSmall'], - icon: ['h-full w-full rounded-lg p-1'], - }, - }, - }, -); -const iconStyles = cva('flex', { - variants: { - border: { - none: 'border-none', - }, - variant: { - primary: ['text-sui-light group-active:text-steel/70 group-disabled:text-steel/50'], - secondary: [ - 'text-steel', - 'group-hover:text-steel-darker group-focus:text-steel-darker', - 'group-active:text-steel-dark/70', - 'group-disabled:text-steel/50', - ], - secondarySui: [ - 'text-steel', - 'group-hover:text-hero group-focus:text-hero', - 'group-active:text-hero/70', - 'group-disabled:text-hero/50', - ], - outline: [ - 'text-steel', - 'group-hover:text-steel-darker group-focus:text-steel-darker', - 'group-active:text-steel-dark', - 'group-disabled:text-gray-45', - ], - outlineWarning: [ - 'text-issue-dark/80', - 'group-hover:text-issue-dark group-focus:text-issue-dark', - 'group-active:text-issue/70', - 'group-disabled:text-issue/50', - ], - warning: [ - 'text-issue-dark/80', - 'group-hover:text-issue-dark group-focus:text-issue-dark', - 'group-active:text-issue/70', - 'group-disabled:text-issue/50', - ], - plain: [], - hidden: [], - }, - }, -}); - -export interface ButtonProps - extends VariantProps, - VariantProps, - Omit { - before?: ReactNode; - after?: ReactNode; - text?: ReactNode; -} - -export const Button = forwardRef( - ( - { variant = 'primary', size = 'narrow', before, after, text, ...otherProps }: ButtonProps, - ref: Ref, - ) => { - return ( - - {before ?
    {before}
    : null} - {text ?
    {text}
    : null} - {after ?
    {after}
    : null} -
    - ); - }, -); diff --git a/apps/wallet/src/ui/app/shared/ConfirmationModal.stories.tsx b/apps/wallet/src/ui/app/shared/ConfirmationModal.stories.tsx deleted file mode 100644 index 3541c12cd9768..0000000000000 --- a/apps/wallet/src/ui/app/shared/ConfirmationModal.stories.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Meta, type StoryObj } from '@storybook/react'; -import { useState } from 'react'; - -import { Button } from './ButtonUI'; -import { ConfirmationModal } from './ConfirmationModal'; - -export default { - component: ConfirmationModal, - decorators: [ - (Story, ctx) => { - const [isOpen, setIsOpen] = useState(false); - return ( - <> -
    - - - - ); -} diff --git a/apps/wallet/src/ui/app/shared/Dialog.tsx b/apps/wallet/src/ui/app/shared/Dialog.tsx deleted file mode 100644 index ac8cb467fb07e..0000000000000 --- a/apps/wallet/src/ui/app/shared/Dialog.tsx +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import * as RadixDialog from '@radix-ui/react-dialog'; -import { cx } from 'class-variance-authority'; -import * as React from 'react'; - -const Dialog = RadixDialog.Root; -const DialogTrigger = RadixDialog.Trigger; -const DialogClose = RadixDialog.Close; - -const DialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogOverlay.displayName = RadixDialog.Overlay.displayName; - -const DialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { background?: 'white' | 'avocado' } ->(({ className, background = 'white', ...props }, ref) => { - return ( - - - - - ); -}); -DialogContent.displayName = RadixDialog.Content.displayName; - -const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( -
    -); - -const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( -
    -); - -const DialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogTitle.displayName = RadixDialog.Title.displayName; - -const DialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DialogDescription.displayName = RadixDialog.Description.displayName; - -export { - Dialog, - DialogClose, - DialogTrigger, - DialogContent, - DialogHeader, - DialogFooter, - DialogTitle, - DialogDescription, -}; diff --git a/apps/wallet/src/ui/app/shared/ExpandableList.tsx b/apps/wallet/src/ui/app/shared/ExpandableList.tsx deleted file mode 100644 index 882fa219f8b27..0000000000000 --- a/apps/wallet/src/ui/app/shared/ExpandableList.tsx +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ChevronDown12 } from '@mysten/icons'; -import clsx from 'clsx'; -import { useMemo, useState, type ReactNode } from 'react'; - -import { Link } from './Link'; -import { Text } from './text'; - -interface ExpandableListProps { - items: ReactNode[]; - defaultItemsToShow: number; -} - -export function ExpandableList({ items, defaultItemsToShow }: ExpandableListProps) { - const [showAll, setShowAll] = useState(false); - - const itemsDisplayed = useMemo( - () => (showAll ? items : items?.slice(0, defaultItemsToShow)), - [showAll, items, defaultItemsToShow], - ); - - const handleShowAllClick = () => setShowAll((prevShowAll: boolean) => !prevShowAll); - - return ( - <> - {itemsDisplayed.map((item, index) => ( -
    {item}
    - ))} - {items.length > defaultItemsToShow && ( -
    - - } - > - {showAll ? 'Show Less' : 'Show All'} - -
    - )} - - ); -} diff --git a/apps/wallet/src/ui/app/shared/InputWithAction.stories.tsx b/apps/wallet/src/ui/app/shared/InputWithAction.stories.tsx deleted file mode 100644 index 355ec8cabf2a1..0000000000000 --- a/apps/wallet/src/ui/app/shared/InputWithAction.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useState } from '@storybook/client-api'; -import { type Meta, type StoryObj } from '@storybook/react'; -import { Form, Formik } from 'formik'; - -import { InputWithAction } from './InputWithAction'; - -export default { - component: InputWithAction, - decorators: [ - (Story) => { - const [value, setValue] = useState(1); - return ( - { - await new Promise((r) => setTimeout(r, 2000)); - setValue(num); - }} - enableReinitialize - > -
    - - -
    - ); - }, - ], -} as Meta; - -export const Default: StoryObj = { - render: (props) => , - args: { - name: 'num', - actionText: 'Save', - placeholder: 'Number placeholder', - }, -}; diff --git a/apps/wallet/src/ui/app/shared/InputWithAction.tsx b/apps/wallet/src/ui/app/shared/InputWithAction.tsx deleted file mode 100644 index 2e1938518c988..0000000000000 --- a/apps/wallet/src/ui/app/shared/InputWithAction.tsx +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import LoadingIndicator from '_components/loading/LoadingIndicator'; -import NumberInput from '_components/number-input'; -import { cva, type VariantProps } from 'class-variance-authority'; -import clsx from 'clsx'; -import { useField, useFormikContext } from 'formik'; -import type { ComponentProps, ReactNode } from 'react'; -import { forwardRef } from 'react'; - -import Alert from '../components/alert'; -import { Pill, type PillProps } from './Pill'; - -const styles = cva( - [ - 'transition flex flex-row items-center p-3 bg-white text-body font-semibold', - 'placeholder:text-gray-60 w-full pr-[calc(20%_+_24px)] shadow-button', - 'border-solid border border-gray-45 text-steel-darker hover:border-steel focus:border-steel', - 'disabled:border-gray-40 disabled:text-gray-55', - ], - { - variants: { - rounded: { - lg: 'rounded-2lg', - md: 'rounded-md', - }, - // TODO: handle dark outline Pill - dark: { - true: '', - false: '', - }, - }, - defaultVariants: { - rounded: 'lg', - dark: false, - }, - }, -); - -type ActionButtonProps = { - actionText?: string; - onActionClicked?: PillProps['onClick']; - actionType?: PillProps['type']; - name: string; - actionDisabled?: boolean | 'auto'; -}; - -export type InputWithActionProps = VariantProps & - ( - | (Omit, 'className' | 'type'> & { - type?: 'text' | 'number' | 'password' | 'email'; - }) - | (Omit, 'form' | 'field' | 'meta'> & { - type: 'numberInput'; - }) - ) & - ActionButtonProps; - -export function InputWithAction({ - actionText, - onActionClicked, - actionType = 'submit', - type, - disabled = false, - actionDisabled = false, - name, - dark, - rounded, - ...props -}: InputWithActionProps) { - const [field, meta] = useField(name); - const form = useFormikContext(); - const { isSubmitting } = form; - const isInputDisabled = isSubmitting || disabled; - const isActionDisabled = - actionDisabled === 'auto' - ? isInputDisabled || meta?.initialValue === meta?.value || !!meta?.error - : actionDisabled; - - return ( - <> -
    - {type === 'numberInput' ? ( - - ) : ( - - )} -
    - -
    -
    - - {(meta?.touched && meta?.error) || (meta.value !== '' && meta.error) ? ( -
    - {meta?.error} -
    - ) : null} - - ); -} - -const inputWithActionZodFormStyles = cva( - [ - 'transition flex flex-row items-center px-3 py-2 text-body font-semibold overflow-hidden', - 'placeholder:text-gray-60 w-full pr-[calc(20%_+_24px)]', - 'border-solid border text-steel-darker', - 'relative', - ], - { - variants: { - rounded: { - lg: 'rounded-2lg', - md: 'rounded-md', - }, - noBorder: { - true: 'border-transparent', - false: '', - }, - disabled: { - true: 'bg-gray-40', - false: 'bg-white hover:border-steel focus:border-steel', - }, - }, - defaultVariants: { - rounded: 'lg', - noBorder: false, - }, - compoundVariants: [ - { - noBorder: false, - disabled: true, - class: 'border-hero-darkest/10', - }, - { - noBorder: false, - disabled: false, - class: 'border-steel', - }, - ], - }, -); - -type InputWithActionZodFormProps = VariantProps & - (Omit, 'className' | 'type'> & { - type?: 'text' | 'number' | 'password' | 'email'; - }) & - ActionButtonProps & { - errorString?: string; - suffix?: ReactNode; - prefix?: ReactNode; - loading?: boolean; - loadingText?: string; - onActionClicked?: PillProps['onClick']; - info?: ReactNode; - actionDisabled?: boolean; - }; - -export const InputWithActionButton = forwardRef( - ( - { - actionText, - onActionClicked, - actionType = 'submit', - type, - disabled = false, - actionDisabled = false, - rounded, - errorString, - value, - suffix, - prefix, - info, - noBorder, - loading, - loadingText, - ...props - }, - forwardRef, - ) => { - const prefixContent = prefix ? ( - - - {prefix} - - - ) : null; - - return ( - <> -
    - {prefixContent} - - {loading && ( -
    -
    - - {loadingText && ( - - {loadingText} - - )} -
    -
    - )} - {suffix && value && ( -
    - {prefixContent} - {value} - {suffix} -
    - )} - - {(onActionClicked || info) && ( -
    - {info} - {onActionClicked && ( - - )} -
    - )} -
    - - {errorString ? ( -
    - {errorString} -
    - ) : null} - - ); - }, -); diff --git a/apps/wallet/src/ui/app/shared/LargeButton.tsx b/apps/wallet/src/ui/app/shared/LargeButton.tsx deleted file mode 100644 index 99faac19003e3..0000000000000 --- a/apps/wallet/src/ui/app/shared/LargeButton.tsx +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import LoadingIndicator from '_components/loading/LoadingIndicator'; -import clsx from 'clsx'; -import { forwardRef, type ReactNode, type Ref } from 'react'; - -import { ButtonOrLink, type ButtonOrLinkProps } from './utils/ButtonOrLink'; - -function Decorator({ disabled, children }: { disabled?: boolean; children: ReactNode }) { - return ( -
    - {children} -
    - ); -} - -interface LargeButtonProps extends ButtonOrLinkProps { - children: ReactNode; - loading?: boolean; - before?: ReactNode; - after?: ReactNode; - top?: ReactNode; - spacing?: string; - center?: boolean; - disabled?: boolean; - primary?: boolean; -} - -export const LargeButton = forwardRef( - ( - { - top, - before, - after, - center, - spacing, - loading, - disabled, - children, - primary, - className, - ...otherProps - }: LargeButtonProps, - ref: Ref, - ) => { - return ( - - {loading && ( -
    - -
    - )} - {!loading && ( -
    - {before && {before}} -
    - {top && {top}} -
    - {children} -
    -
    - {after && ( -
    - {after} -
    - )} -
    - )} -
    - ); - }, -); diff --git a/apps/wallet/src/ui/app/shared/Link.stories.tsx b/apps/wallet/src/ui/app/shared/Link.stories.tsx deleted file mode 100644 index fb8c81816e31b..0000000000000 --- a/apps/wallet/src/ui/app/shared/Link.stories.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ArrowUpRight12 } from '@mysten/icons'; -import { type Meta, type StoryObj } from '@storybook/react'; - -import { Link } from './Link'; - -export default { - component: Link, -} as Meta; - -export const Default: StoryObj = { - render: (props) => ( - <> - - - alert('Hello')} /> - - - alert('Hello')} disabled /> - - - alert('Hello')} loading /> - - ), - args: { - text: 'Default Link', - after: , - color: 'steelDark', - weight: 'semibold', - }, -}; diff --git a/apps/wallet/src/ui/app/shared/Link.tsx b/apps/wallet/src/ui/app/shared/Link.tsx deleted file mode 100644 index f7db089bfe2b7..0000000000000 --- a/apps/wallet/src/ui/app/shared/Link.tsx +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; -import { forwardRef, type ReactNode, type Ref } from 'react'; - -import { ButtonOrLink, type ButtonOrLinkProps } from './utils/ButtonOrLink'; - -const styles = cva( - [ - 'transition flex flex-nowrap items-center justify-center outline-none gap-1 w-full', - 'bg-transparent p-0 border-none', - 'active:opacity-70', - 'disabled:opacity-40', - 'cursor-pointer group', - ], - { - variants: { - underline: { - none: 'no-underline', - hover: 'no-underline hover:underline', - }, - color: { - steelDark: [ - 'text-steel-dark hover:text-steel-darker focus:text-steel-darker disabled:text-steel-dark', - ], - steelDarker: [ - 'text-steel-darker hover:text-steel-darker focus:text-steel-darker disabled:text-steel-darker', - ], - heroDark: [ - 'text-hero-dark hover:text-hero-darkest focus:text-hero-darkest disabled:text-hero-dark', - ], - suiDark: ['text-sui-dark'], - hero: ['text-hero hover:text-hero-dark focus:text-hero-dark disabled:text-hero-dark'], - }, - weight: { - semibold: 'font-semibold', - medium: 'font-medium', - }, - size: { - bodySmall: 'text-bodySmall', - body: 'text-body', - base: 'text-base leading-none', - captionSmall: 'text-captionSmall', - }, - mono: { - true: 'font-mono', - false: '', - }, - }, - }, -); - -const iconStyles = cva(['transition flex'], { - variants: { - beforeColor: { - steelDarker: ['text-steel-darker'], - }, - color: { - steelDark: [ - 'text-steel group-hover:text-steel-darker group-focus:text-steel-darker group-disabled:text-steel-dark', - ], - steelDarker: [ - 'text-steel-darker group-hover:text-steel-darker group-focus:text-steel-darker group-disabled:text-steel-darker', - ], - heroDark: [ - 'text-hero group-hover:text-hero-darkest group-focus:text-hero-darkest group-disabled:text-hero-dark', - ], - suiDark: [ - 'text-steel group-hover:text-sui-dark group-focus:text-sui-dark group-disabled:text-steel', - ], - hero: [ - 'text-hero group-hover:text-hero-dark group-focus:text-hero-dark group-disabled:text-hero-dark', - ], - }, - }, -}); - -export interface LinkProps - extends VariantProps, - VariantProps, - Omit { - before?: ReactNode; - after?: ReactNode; - text?: ReactNode; -} - -export const Link = forwardRef( - ( - { - before, - beforeColor, - after, - text, - color, - weight, - size = 'bodySmall', - underline = 'none', - mono, - ...otherProps - }: LinkProps, - ref: Ref, - ) => ( - - {before ? ( -
    - {before} -
    - ) : null} - {text ?
    {text}
    : null} - {after ?
    {after}
    : null} -
    - ), -); diff --git a/apps/wallet/src/ui/app/shared/PageTitle.stories.tsx b/apps/wallet/src/ui/app/shared/PageTitle.stories.tsx deleted file mode 100644 index 5fc7fab109351..0000000000000 --- a/apps/wallet/src/ui/app/shared/PageTitle.stories.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Meta, type StoryObj } from '@storybook/react'; - -import PageTitle from './PageTitle'; - -export default { - component: PageTitle, -} as Meta; - -export const Default: StoryObj = { - args: { - title: 'Title', - }, -}; - -export const BackUrl: StoryObj = { - args: { - title: 'Title', - back: '/', - }, -}; - -export const BackCallback: StoryObj = { - args: { - title: 'Title', - back: () => alert('Back clicked'), - }, -}; - -export const BackTrue: StoryObj = { - args: { - title: 'Title', - back: true, - }, -}; - -export const BackLongTitle: StoryObj = { - args: { - title: 'AVeryVeryVeeeeeeeeryLoooooongTitle', - back: true, - }, -}; diff --git a/apps/wallet/src/ui/app/shared/PageTitle.tsx b/apps/wallet/src/ui/app/shared/PageTitle.tsx deleted file mode 100644 index 500174a92e978..0000000000000 --- a/apps/wallet/src/ui/app/shared/PageTitle.tsx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ArrowLeft16 } from '@mysten/icons'; -import { type ReactNode } from 'react'; -import { useNavigate } from 'react-router-dom'; - -import { Button } from './ButtonUI'; -import { Heading } from './heading'; - -export type PageTitleProps = { - title?: string; - back?: boolean | string | (() => void); - after?: ReactNode; -}; - -function PageTitle({ title = '', back, after }: PageTitleProps) { - const navigate = useNavigate(); - const backOnClick = - back && typeof back !== 'string' - ? () => { - if (typeof back === 'function') { - back(); - return; - } - navigate(-1); - } - : undefined; - return ( -
    - {after && !back ?
    : null} - {back ? ( -
    -
    - ) : null} -
    - - {title} - -
    - {back ?
    {after}
    : after} -
    - ); -} - -export default PageTitle; diff --git a/apps/wallet/src/ui/app/shared/Pill.stories.tsx b/apps/wallet/src/ui/app/shared/Pill.stories.tsx deleted file mode 100644 index e7282972c365e..0000000000000 --- a/apps/wallet/src/ui/app/shared/Pill.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { type Meta, type StoryObj } from '@storybook/react'; - -import { Pill } from './Pill'; - -export default { - component: Pill, -} as Meta; - -export const Default: StoryObj = { - render: (props) => ( -
    - - - alert('Hello')} /> - - - alert('Hello')} disabled /> - - - alert('Hello')} loading /> -
    - ), - args: { - text: 'Default Link', - }, -}; diff --git a/apps/wallet/src/ui/app/shared/Pill.tsx b/apps/wallet/src/ui/app/shared/Pill.tsx deleted file mode 100644 index 026d6e0f5ec36..0000000000000 --- a/apps/wallet/src/ui/app/shared/Pill.tsx +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; -import { forwardRef, type ReactNode, type Ref } from 'react'; - -import { ButtonOrLink, type ButtonOrLinkProps } from './utils/ButtonOrLink'; - -const styles = cva( - [ - 'inline-block outline-none transition no-underline bg-white py-1 px-2', - 'border border-solid rounded-20 cursor-pointer', - 'truncate leading-tight uppercase text-captionSmall font-semibold', - 'disabled:border-transparent disabled:text-gray-60', - ], - { - variants: { - loading: { - true: 'bg-white border-gray-45 text-steel disabled:border-gray-45 disabled:text-steel', - false: '', - }, - dark: { - true: 'border-gray-60 text-steel-darker hover:border-steel-darker hover:text-steel-darker disabled:bg-gray-40 font-medium', - false: - 'border-sui-light text-hero-dark active:bg-gray-45 active:text-steel-darker active:border-gray-45 disabled:bg-white hover:bg-sui-light focus:bg-sui-light', - }, - }, - defaultVariants: { - dark: false, - }, - }, -); - -export interface PillProps - extends Omit, 'loading'>, - Omit { - before?: ReactNode; - after?: ReactNode; - text?: ReactNode; -} - -export const Pill = forwardRef( - ( - { before, after, text, loading, dark, ...otherProps }: PillProps, - ref: Ref, - ) => ( - - {text} - - ), -); diff --git a/apps/wallet/src/ui/app/shared/Portal.tsx b/apps/wallet/src/ui/app/shared/Portal.tsx deleted file mode 100644 index ba580fb8fa5c1..0000000000000 --- a/apps/wallet/src/ui/app/shared/Portal.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { useEffect, useState } from 'react'; -import { createPortal } from 'react-dom'; - -type PortalProps = { - children: React.ReactNode; - containerId: string; -}; - -export function Portal({ children, containerId }: PortalProps) { - const [hasMounted, setHasMounted] = useState(false); - - useEffect(() => { - setHasMounted(true); - }, []); - - if (!hasMounted) { - return null; - } - - return createPortal(children, document.getElementById(containerId)!); -} diff --git a/apps/wallet/src/ui/app/shared/SocialButton.tsx b/apps/wallet/src/ui/app/shared/SocialButton.tsx deleted file mode 100644 index fc7eff0325805..0000000000000 --- a/apps/wallet/src/ui/app/shared/SocialButton.tsx +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { - SocialFacebook24, - SocialGoogle24, - SocialKakao24, - SocialMicrosoft24, - SocialTwitch24, -} from '@mysten/icons'; -import { cva, type VariantProps } from 'class-variance-authority'; -import { forwardRef, type FunctionComponent, type Ref, type SVGProps } from 'react'; - -import { ButtonOrLink, type ButtonOrLinkProps } from './utils/ButtonOrLink'; - -const styles = cva( - 'h-10 w-full cursor-pointer rounded-xl inline-flex items-center justify-center gap-3 px-4 py-2 disabled:opacity-40 focus:opacity-80', - { - variants: { - provider: { - microsoft: - 'bg-white text-steel-dark border border-solid border-steel hover:border-steel-dark', - google: 'bg-white text-steel-dark border border-solid border-steel hover:border-steel-dark', - facebook: 'bg-facebook border-none text-white', - twitch: 'bg-twitch border-none text-white', - kakao: 'bg-kakao border-none text-black/85', - }, - }, - }, -); - -type StyleProps = VariantProps; -type SocialSignInProvider = NonNullable; - -type SocialButtonProps = { - showLabel?: boolean; - provider: SocialSignInProvider; -} & Omit & - StyleProps; - -const socialSignInProviderInfo: Record< - SocialSignInProvider, - { icon: FunctionComponent>; label: string } -> = { - microsoft: { - icon: SocialMicrosoft24, - label: 'Sign in with Microsoft', - }, - google: { - icon: SocialGoogle24, - label: 'Sign in with Google', - }, - facebook: { - icon: SocialFacebook24, - label: 'Sign in with Facebook', - }, - twitch: { - icon: SocialTwitch24, - label: 'Sign in with Twitch', - }, - kakao: { - icon: SocialKakao24, - label: 'Sign in with Kakao', - }, -}; - -export const SocialButton = forwardRef( - ( - { provider, showLabel = false, ...otherProps }: SocialButtonProps, - forwardedRef: Ref, - ) => { - const { icon: IconComponent, label } = socialSignInProviderInfo[provider]; - return ( - - - {showLabel && ( - - {label} - - )} - - ); - }, -); diff --git a/apps/wallet/src/ui/app/shared/bottom-menu-layout/BottomMenuLayout.module.scss b/apps/wallet/src/ui/app/shared/bottom-menu-layout/BottomMenuLayout.module.scss deleted file mode 100644 index d01215d4a882d..0000000000000 --- a/apps/wallet/src/ui/app/shared/bottom-menu-layout/BottomMenuLayout.module.scss +++ /dev/null @@ -1,32 +0,0 @@ -@use '_utils'; -@use '_variables' as v; - -.container { - display: flex; - flex-flow: column nowrap; - flex-grow: 1; - overflow-y: auto; - overflow-x: visible; - - @include utils.override-main-sides-space; -} - -.content { - flex-grow: 1; -} - -.menu { - display: flex; - flex-flow: row nowrap; - position: sticky; - bottom: -1px; - background-color: v.use(v.$colors-main-content-background); - padding: 15px 25px 25px; - margin-top: 12px; - align-items: center; - justify-content: stretch; - gap: 10px; - transition: all 200ms ease-in-out; - - @include utils.escape-main-sides-space; -} diff --git a/apps/wallet/src/ui/app/shared/bottom-menu-layout/index.tsx b/apps/wallet/src/ui/app/shared/bottom-menu-layout/index.tsx deleted file mode 100644 index a2fe0a2103d32..0000000000000 --- a/apps/wallet/src/ui/app/shared/bottom-menu-layout/index.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import cl from 'clsx'; -import { Children, memo, useEffect, useRef, useState } from 'react'; -import type { ReactNode } from 'react'; - -import st from './BottomMenuLayout.module.scss'; - -export type BottomMenuLayoutProps = { - className?: string; - children: [ReactNode, ReactNode]; -}; - -function BottomMenuLayout({ className, children }: BottomMenuLayoutProps) { - if (Children.count(children) < 2) { - //eslint-disable-next-line no-console - console.warn( - '[BottomMenuLayout] expects 2 children. First child should be the content and the second the bottom menu', - ); - } - return
    {children}
    ; -} - -type ContentMenuProps = { - className?: string; - children: ReactNode | ReactNode[]; -}; - -function ContentNoMemo({ className, children }: ContentMenuProps) { - return
    {children}
    ; -} - -function MenuNoMemo({ - className, - children, - stuckClass, -}: ContentMenuProps & { stuckClass: string }) { - const [isStuck, setIsStuck] = useState(false); - const menuRef = useRef(null); - useEffect(() => { - if (menuRef.current) { - const observer = new IntersectionObserver( - ([entry]) => { - setIsStuck(entry.intersectionRatio < 1); - }, - { threshold: 1 }, - ); - observer.observe(menuRef.current); - return () => { - observer.disconnect(); - }; - } - }); - return ( -
    - {children} -
    - ); -} - -export default memo(BottomMenuLayout); -export const Content = memo(ContentNoMemo); -export const Menu = memo(MenuNoMemo); diff --git a/apps/wallet/src/ui/app/shared/card-layout/index.tsx b/apps/wallet/src/ui/app/shared/card-layout/index.tsx deleted file mode 100644 index e4f7234334dab..0000000000000 --- a/apps/wallet/src/ui/app/shared/card-layout/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Heading } from '_app/shared/heading'; -import { Text } from '_app/shared/text'; -import { Sui, ThumbUpFill32 } from '@mysten/icons'; -import type { ReactNode } from 'react'; - -export type CardLayoutProps = { - title?: string; - subtitle?: string; - headerCaption?: string; - icon?: 'success' | 'sui'; - children: ReactNode | ReactNode[]; -}; - -export function CardLayout({ children, title, subtitle, headerCaption, icon }: CardLayoutProps) { - return ( -
    - {icon === 'success' ? ( -
    -
    - -
    -
    - ) : null} - {icon === 'sui' ? ( -
    - -
    - ) : null} - {headerCaption ? ( - - {headerCaption} - - ) : null} - {title ? ( -
    - - {title} - -
    - ) : null} - {subtitle ? ( -
    - - {subtitle} - -
    - ) : null} - {children} -
    - ); -} diff --git a/apps/wallet/src/ui/app/shared/card/CardItem.tsx b/apps/wallet/src/ui/app/shared/card/CardItem.tsx deleted file mode 100644 index 806452dd93193..0000000000000 --- a/apps/wallet/src/ui/app/shared/card/CardItem.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import type { ReactNode } from 'react'; - -export type CardItemProps = { - title: ReactNode; - children: ReactNode; -}; - -export function CardItem({ title, children }: CardItemProps) { - return ( -
    - - {title} - - - {children} -
    - ); -} diff --git a/apps/wallet/src/ui/app/shared/card/index.tsx b/apps/wallet/src/ui/app/shared/card/index.tsx deleted file mode 100644 index d5c8241ea37b4..0000000000000 --- a/apps/wallet/src/ui/app/shared/card/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; -import type { ReactNode } from 'react'; - -const cardContentStyle = cva([], { - variants: { - variant: { - white: 'bg-white', - gray: 'bg-gray-40', - }, - padding: { - none: 'p-0', - small: 'p-3.5', - }, - titleDivider: { - true: 'border-t border-t-gray-45 border-solid border-0 border-transparent', - }, - }, - defaultVariants: { - variant: 'white', - padding: 'small', - }, -}); - -export interface CardProps extends VariantProps { - header?: ReactNode; - footer?: ReactNode; - children?: ReactNode; -} - -export function Card({ header, footer, children, ...styleProps }: CardProps) { - return ( -
    - {header &&
    {header}
    } -
    - {children} - {footer && ( -
    - {children && } -
    {footer}
    -
    - )} -
    -
    - ); -} - -export { CardItem } from './CardItem'; diff --git a/apps/wallet/src/ui/app/shared/coin-balance/index.tsx b/apps/wallet/src/ui/app/shared/coin-balance/index.tsx deleted file mode 100644 index 97f74b2fa2af0..0000000000000 --- a/apps/wallet/src/ui/app/shared/coin-balance/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { useFormatCoin } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui/utils'; - -//TODO create variant for different use cases like heading4, subtitle, bodySmall and different symbols color -interface CoinBalanceProps { - amount: bigint | number | string; - coinType?: string; -} - -export function CoinBalance({ amount, coinType }: CoinBalanceProps) { - const [formatted, symbol] = useFormatCoin(amount, coinType || SUI_TYPE_ARG); - - return Math.abs(Number(amount)) > 0 ? ( -
    - - {formatted} - - - {symbol} - -
    - ) : null; -} diff --git a/apps/wallet/src/ui/app/shared/collapse/index.tsx b/apps/wallet/src/ui/app/shared/collapse/index.tsx deleted file mode 100644 index f5912605c7582..0000000000000 --- a/apps/wallet/src/ui/app/shared/collapse/index.tsx +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ChevronDown12, ChevronRight12 } from '@mysten/icons'; -import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; -import cn from 'clsx'; -import { useState, type ReactNode } from 'react'; - -interface CollapsibleProps { - title: string; - defaultOpen?: boolean; - children: ReactNode | ReactNode[]; - shade?: 'lighter' | 'darker'; - isOpen?: boolean; - onOpenChange?: (isOpen: boolean) => void; -} - -export function Collapsible({ - title, - children, - defaultOpen, - isOpen, - onOpenChange, - shade = 'lighter', -}: CollapsibleProps) { - const [open, setOpen] = useState(isOpen ?? defaultOpen ?? false); - - const handleOpenChange = (isOpen: boolean) => { - setOpen(isOpen); - onOpenChange?.(isOpen); - }; - - return ( - - -
    - {title} -
    -
    -
    - {open ? : } -
    - - - {children} - - ); -} diff --git a/apps/wallet/src/ui/app/shared/countdown-timer/index.tsx b/apps/wallet/src/ui/app/shared/countdown-timer/index.tsx deleted file mode 100644 index f327313ceb44d..0000000000000 --- a/apps/wallet/src/ui/app/shared/countdown-timer/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { TimeUnit, useTimeAgo } from '@mysten/core'; -import { cva, type VariantProps } from 'class-variance-authority'; - -const timeStyle = cva([], { - variants: { - variant: { - body: 'text-body', - bodySmall: 'text-bodySmall', - }, - color: { - 'steel-dark': 'text-steel-dark', - 'steel-darker': 'text-steel-darker', - }, - weight: { - medium: 'font-medium', - semibold: 'font-semibold', - }, - }, - defaultVariants: { - variant: 'body', - color: 'steel-dark', - weight: 'semibold', - }, -}); - -export interface CountDownTimerProps extends VariantProps { - timestamp: number | undefined; - label?: string; - endLabel?: string; -} - -export function CountDownTimer({ - timestamp, - label, - endLabel = 'now', - ...styles -}: CountDownTimerProps) { - const timeAgo = useTimeAgo({ - timeFrom: timestamp || null, - shortedTimeLabel: false, - shouldEnd: true, - endLabel: endLabel, - maxTimeUnit: TimeUnit.ONE_HOUR, - }); - - return ( -
    - {timeAgo === endLabel ? '' : label} {timeAgo} -
    - ); -} diff --git a/apps/wallet/src/ui/app/shared/dapp-status/DappStatus.module.scss b/apps/wallet/src/ui/app/shared/dapp-status/DappStatus.module.scss deleted file mode 100644 index 9790648897a5f..0000000000000 --- a/apps/wallet/src/ui/app/shared/dapp-status/DappStatus.module.scss +++ /dev/null @@ -1,86 +0,0 @@ -@use '_values/colors'; -@use '_utils'; - -.icon { - font-size: 6px; - color: colors.$success; -} - -.chevron { - font-size: 11px; -} - -.popup { - position: absolute; - background: colors.$gray-100; - border-radius: 6px; - padding: 10px 12px; - z-index: 999; - max-width: 55%; - top: 0; - left: 0; -} - -.popup-content { - display: flex; - flex-flow: column nowrap; - align-items: center; -} - -.popup-arrow { - position: absolute; - z-index: -1; - top: -6px; - - &::before { - content: ''; - background: colors.$gray-100; - transform: rotate(45deg); - height: 12px; - width: 12px; - display: block; - } -} - -.origin-container { - display: flex; - flex-flow: row nowrap; - align-items: center; -} - -.favicon { - width: 22px; - height: 22px; - border-radius: 6px; - background-color: colors.$gray-85; - margin-right: 8px; - padding: 2px; -} - -.origin-text { - @include utils.overflow-ellipsis; - @include utils.typography('Primary/SubtitleSmall-M'); - - color: white; -} - -.origin-url { - @include utils.typography('Primary/BodySmall-SB'); -} - -.divider { - height: 1px; - background-color: colors.$gray-90; - margin: 8px 0; - align-self: stretch; -} - -.disconnect { - background: none; - outline: none; - border: none; - color: colors.$issue; - cursor: pointer; - - @include utils.typography('Primary/BodySmall-M'); -} diff --git a/apps/wallet/src/ui/app/shared/dapp-status/actions/index.ts b/apps/wallet/src/ui/app/shared/dapp-status/actions/index.ts deleted file mode 100644 index 8e56b037ddf77..0000000000000 --- a/apps/wallet/src/ui/app/shared/dapp-status/actions/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { AppThunkConfig } from '_redux/store/thunk-extras'; -import { createAsyncThunk } from '@reduxjs/toolkit'; - -export const appDisconnect = createAsyncThunk< - void, - { origin: string; accounts: string[] }, - AppThunkConfig ->('dapp-status-app-disconnect', async ({ origin, accounts }, { extra: { background } }) => { - await background.disconnectApp(origin, accounts); - await background.sendGetPermissionRequests(); -}); diff --git a/apps/wallet/src/ui/app/shared/dapp-status/index.tsx b/apps/wallet/src/ui/app/shared/dapp-status/index.tsx deleted file mode 100644 index cac619e30a569..0000000000000 --- a/apps/wallet/src/ui/app/shared/dapp-status/index.tsx +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import Loading from '_components/loading'; -import { useAppDispatch, useAppSelector } from '_hooks'; -import { createDappStatusSelector } from '_redux/slices/permissions'; -import { ampli } from '_src/shared/analytics/ampli'; -import { - arrow, - offset, - useClick, - useDismiss, - useFloating, - useInteractions, -} from '@floating-ui/react'; -import { ChevronDown12, Dot12 } from '@mysten/icons'; -import { AnimatePresence, motion } from 'framer-motion'; -import { memo, useCallback, useMemo, useRef, useState } from 'react'; - -import { useActiveAddress } from '../../hooks/useActiveAddress'; -import { ButtonConnectedTo } from '../ButtonConnectedTo'; -import { appDisconnect } from './actions'; -import st from './DappStatus.module.scss'; - -function DappStatus() { - const dispatch = useAppDispatch(); - const activeOriginUrl = useAppSelector(({ app }) => app.activeOrigin); - const activeOrigin = useMemo(() => { - try { - return (activeOriginUrl && new URL(activeOriginUrl).hostname) || null; - } catch (e) { - return null; - } - }, [activeOriginUrl]); - const activeOriginFavIcon = useAppSelector(({ app }) => app.activeOriginFavIcon); - const activeAddress = useActiveAddress(); - const dappStatusSelector = useMemo( - () => createDappStatusSelector(activeOriginUrl, activeAddress), - [activeOriginUrl, activeAddress], - ); - const isConnected = useAppSelector(dappStatusSelector); - const [disconnecting, setDisconnecting] = useState(false); - const [visible, setVisible] = useState(false); - const onHandleClick = useCallback( - (e: boolean) => { - if (!disconnecting) { - setVisible((isVisible) => !isVisible); - } - }, - [disconnecting], - ); - const arrowRef = useRef(null); - const { - x, - y, - context, - reference, - refs, - middlewareData: { arrow: arrowData }, - } = useFloating({ - open: visible, - onOpenChange: onHandleClick, - placement: 'bottom', - middleware: [offset(8), arrow({ element: arrowRef })], - }); - const { getFloatingProps, getReferenceProps } = useInteractions([ - useClick(context), - useDismiss(context, { - outsidePressEvent: 'click', - bubbles: false, - }), - ]); - const onHandleDisconnect = useCallback(async () => { - if (!disconnecting && isConnected && activeOriginUrl && activeAddress) { - setDisconnecting(true); - try { - await dispatch( - appDisconnect({ - origin: activeOriginUrl, - accounts: [activeAddress], - }), - ).unwrap(); - ampli.disconnectedApplication({ - applicationUrl: activeOriginUrl, - disconnectedAccounts: 1, - sourceFlow: 'Header', - }); - setVisible(false); - } catch (e) { - // Do nothing - } finally { - setDisconnecting(false); - } - } - }, [disconnecting, isConnected, activeOriginUrl, activeAddress, dispatch]); - if (!isConnected) { - return null; - } - return ( - <> - } - text={activeOrigin || ''} - iconAfter={} - ref={reference} - {...getReferenceProps()} - /> - - {visible ? ( - -
    -
    - {activeOriginFavIcon ? ( - App Icon - ) : null} - -
    Connected to
    -
    {activeOrigin}
    -
    -
    -
    - - - -
    -
    - - ) : null} - - - ); -} - -export default memo(DappStatus); diff --git a/apps/wallet/src/ui/app/shared/date-card/index.tsx b/apps/wallet/src/ui/app/shared/date-card/index.tsx deleted file mode 100644 index 8f39939f88690..0000000000000 --- a/apps/wallet/src/ui/app/shared/date-card/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { formatDate } from '_helpers'; - -type DateCardProps = { - timestamp: number; - size: 'sm' | 'md'; -}; - -export function DateCard({ timestamp, size }: DateCardProps) { - const txnDate = formatDate(timestamp, ['month', 'day', 'hour', 'minute']); - - return ( - - {txnDate} - - ); -} diff --git a/apps/wallet/src/ui/app/shared/delegated-apy/index.tsx b/apps/wallet/src/ui/app/shared/delegated-apy/index.tsx deleted file mode 100644 index 60144828a9a46..0000000000000 --- a/apps/wallet/src/ui/app/shared/delegated-apy/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_app/shared/text'; -import { IconTooltip } from '_app/shared/tooltip'; -import LoadingIndicator from '_components/loading/LoadingIndicator'; -import { roundFloat, useGetValidatorsApy } from '@mysten/core'; -import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { useMemo } from 'react'; - -const APY_DECIMALS = 3; - -type DelegatedAPYProps = { - stakedValidators: string[]; -}; - -export function DelegatedAPY({ stakedValidators }: DelegatedAPYProps) { - const { data, isPending } = useSuiClientQuery('getLatestSuiSystemState'); - const { data: rollingAverageApys } = useGetValidatorsApy(); - - const averageNetworkAPY = useMemo(() => { - if (!data || !rollingAverageApys) return null; - - let stakedAPYs = 0; - - stakedValidators.forEach((validatorAddress) => { - stakedAPYs += rollingAverageApys?.[validatorAddress]?.apy || 0; - }); - - const averageAPY = stakedAPYs / stakedValidators.length; - - return roundFloat(averageAPY || 0, APY_DECIMALS); - }, [data, rollingAverageApys, stakedValidators]); - - if (isPending) { - return ( -
    - -
    - ); - } - - if (!averageNetworkAPY) return null; - - return ( -
    - {averageNetworkAPY !== null ? ( - <> - - {averageNetworkAPY} - - - % APY - -
    - -
    - - ) : ( - - -- - - )} -
    - ); -} diff --git a/apps/wallet/src/ui/app/shared/faucet/FaucetMessageInfo.tsx b/apps/wallet/src/ui/app/shared/faucet/FaucetMessageInfo.tsx deleted file mode 100644 index fbe117a6b69b9..0000000000000 --- a/apps/wallet/src/ui/app/shared/faucet/FaucetMessageInfo.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; -import { useFormatCoin } from '@mysten/core'; - -export type FaucetMessageInfoProps = { - error?: string | null; - loading?: boolean; - totalReceived?: number | null; -}; - -function FaucetMessageInfo({ - error = null, - loading = false, - totalReceived = null, -}: FaucetMessageInfoProps) { - const [coinsReceivedFormatted, coinsReceivedSymbol] = useFormatCoin(totalReceived, GAS_TYPE_ARG); - if (loading) { - return <>Request in progress; - } - if (error) { - return <>{error}; - } - return ( - <>{`${totalReceived ? `${coinsReceivedFormatted} ` : ''}${coinsReceivedSymbol} received`} - ); -} - -export default FaucetMessageInfo; diff --git a/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx b/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx deleted file mode 100644 index b4fc0bd3c041a..0000000000000 --- a/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { API_ENV_TO_INFO } from '_app/ApiProvider'; -import { Button, type ButtonProps } from '_app/shared/ButtonUI'; -import { useAppSelector } from '_hooks'; -import { API_ENV } from '_src/shared/api-env'; -import { FaucetRateLimitError, getFaucetHost } from '@mysten/sui/faucet'; -import { toast } from 'react-hot-toast'; - -import FaucetMessageInfo from './FaucetMessageInfo'; -import { useFaucetMutation } from './useFaucetMutation'; -import { useFaucetRateLimiter } from './useFaucetRateLimiter'; - -export type FaucetRequestButtonProps = { - variant?: ButtonProps['variant']; - size?: ButtonProps['size']; -}; - -export const FAUCET_HOSTS = { - [API_ENV.local]: getFaucetHost('localnet'), - [API_ENV.devNet]: getFaucetHost('devnet'), - [API_ENV.testNet]: getFaucetHost('testnet'), -}; - -function FaucetRequestButton({ variant = 'primary', size = 'narrow' }: FaucetRequestButtonProps) { - const network = useAppSelector(({ app }) => app.apiEnv); - const networkName = API_ENV_TO_INFO[network].name.replace(/sui\s*/gi, ''); - const [isRateLimited, rateLimit] = useFaucetRateLimiter(); - - const mutation = useFaucetMutation({ - host: network in FAUCET_HOSTS ? FAUCET_HOSTS[network as keyof typeof FAUCET_HOSTS] : null, - onError: (error) => { - if (error instanceof FaucetRateLimitError) { - rateLimit(); - } - }, - }); - - return mutation.enabled ? ( -