Skip to content

Forging — A convenient Web3 wallet toolkit for easily generating, importing, and exporting single/batch HD & non-HD wallets. Pluggable design for any chain, with Solana + full EVM support out of the box.

Notifications You must be signed in to change notification settings

BCSuite/Forging

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

- Forging

- Feature

- Installation

- Usage

- Dependencies

Forging

Forging is a convenient and developer-friendly Web3 wallet toolkit that supports generating, importing, and exporting both single and batch HD and non-HD wallets.

Built with a modular, pluggable architecture, it allows seamless extension to any chain and ships with first-class support for Solana and all EVM-compatible chains (Ethereum, BNB Chain, Polygon, Arbitrum, etc.).

iOS 14+ Swift 5.3+ Swift Package Manager Platforms

Feature

  • Generate single or batch HD/Non-HD wallets for any specific chain with one click.

  • Import single or batch HD/non-HD wallets for any specific chain with one click.

  • Export single or batch HD/Non-HD wallets for any specific chain with one click.

  • Generate single or batch HD/non-HD wallets across multiple chains with one click.

  • Import single or batch HD/non-HD wallets across multiple chains with one click.

Installation

SPM

.package(url: "https://https://github.com/BCSuite/Forging.git", from: "0.0.1")

Usage

Non-HD

Generate

  • Single chain.

    • Single wallet

       // Solana.
      let generator = FGNonHDWalletUniGenerator.solana()
      let wallet = try generator.generate()
      print("address:\(wallet.address), privKey:\(wallet.privKey)")
      
      // EVM.
      let generator = FGNonHDWalletUniGenerator.evm()
      let wallet = try generator.generate()
      print("address:\(wallet.address), privKey:\(wallet.privKey)"
      
    • batch wallets

      // Solana.
      let genCnt = 201
      let generator = FGNonHDWalletUniGenerator.solana()
      let wallets = try await generator.batchGenerate(inCount: genCnt)
      for wallet in wallets {
        print("address:\(wallet.address), privKey:\(wallet.privKey)")
      }
      
      // EVM.
      let genCnt = 101
      let generator = FGNonHDWalletUniGenerator.evm()
      let wallets = try await generator.batchGenerate(inCount: genCnt)
      for wallet in wallets {
          print("address:\(wallet.address), privKey:\(wallet.privKey)")
      }
      

      The batchGenerate will ignoring failed cases and continue generating by default. If want to stop once any generation fails, set the isInterruptible param to true .

      let wallets = try await generator.batchGenerate(inCount: genCnt, isInterruptible: true)
      
  • Multi-chain.

    • Single wallet

      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure the generation handler of each chain.
      let handlers = [FGNonHDGenHandler.solana(), FGNonHDGenHandler.evm(serviceSharedChains: evmSharedChains)]
      
      // Create a multi-chain tasks processor.
      let generator = FGMultiChainWalletProcessor(chainHandlers: handlers)
      
      // Generate with the operation kind: FGMultiChainNonHDWalletGenKind.
      let walletMap = try await generator.process(with: .single)
      for (chainName, wallets) in walletMap {
          // Wallets only contains one wallet.
          print("\(chainName)->wallet\(String(describing: wallets.first))")
      }
      
      /// Output ///
      Optimism->wallet: Optional(Forging.FGCryptoWallet(address: "0x1..6”, privKey: “d….9”, mnemonic: nil))
      Solana->Optional(Forging.FGCryptoWallet(address: "GF..JoK", privKey: "59E..”, mnemonic: nil))
      Ethereum-> Optional(Forging.FGCryptoWallet(address: "0x1..b”, privKey: “d..9”, mnemonic: nil))
      Base -> Optional(Forging.FGCryptoWallet(address: "0x1..b”, privKey: “d..9”, mnemonic: nil)
      
    • batch wallets

      let genCnt = 20
      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure the generation handler of each chain.
      let handlers = [FGNonHDGenHandler.solana(), FGNonHDGenHandler.evm(serviceSharedChains: evmSharedChains)]
      
      // Create a multi-chain tasks processor.
      let generator = FGMultiChainWalletProcessor(chainHandlers: handlers)
      
      // Generate with the operation kind of FGMultiChainNonHDWalletGenKind.batch(count:).
      let walletMap = try await generator.process(with: .batch(count: genCnt))
      for (chainName, wallets) in walletMap {
          print("\(chainName):")
          for wallet in wallets {
              print("address:\(wallet.address), privKey:\(wallet.privKey)")
          }
      }
      
      /// Output ///
      Optimism:
      address:0x1…1, privKey:9…8
      address:0x2…5, privKey:7...c
      address:0xf..9, privKey:c..5
      Ethereum:
      address:0x1…1, privKey:9…8
      address:0x2..5, privKey:7..c
      address:0xf..9, privKey:c..5
      Base:
      address:0x1…1, privKey:9…8
      address:0x2..5, privKey:7..c
      address:0xf..9, privKey:c..5
      Solana:
      address:A…k, privKey:5…a
      address:D…s, privKey:3…s
      address:G…5, privKey:M…u
      

Import

  • Solana

    let importer = FGSingleSolNonHDWalletImporter()
    let privKey = "y..a"
    let wallet = try importer.importWallet(from: privKey)
    print("address:\(wallet.address)")
    
  • EVM

     let importer = FGSingleEVMNonHDWalletImporter()
     let privKey = "a..n"
     let importedWallet = try importer.importWallet(from: wallet.privKey)
     print("address:\(wallet.address)")
    

HD

Generate

  • Single chain

    • Single wallet

      /// Solana ///
      
      // Generate a random Solana wallet with 12 words mnemonic.
      let generator = FGHDWalletUniGenerator.solana()
      let wallet = try generator.generate()
      print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic ?? "")")
      
      // Specify the mnemonic words count.
      // - 12 words(default): FGMnemonic12WordsSize
      // - 15 words: FGMnemonic15WordsSize
      // - 18 words: FGMnemonic18WordsSize
      // - 21 words: FGMnemonic21WordsSize
      // - 24 words: FGMnemonic24WordsSize
      let generator = FGHDWalletUniGenerator.solana()
      let mnemonicSize = FGMnemonic24WordsSize.self // or other size.
      let wallet = try generator.generate(atSize: mnemonicSize)
      print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic ?? "")")
      
      // Generate a Solana wallet from a given mnemonic.
      let generator = FGHDWalletUniGenerator.solana()
      let mnemonic = "xx xx..."
      let wallet = try generator.generate(from: mnemonic)
      print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic ?? "")")
        
        
      /// EVM ///
      
      // Gereate a random EVM wallet with 12 words mnemonic.
      let generator = FGHDWalletUniGenerator.evm()
      let wallet = try generator.generate()
      
      // Generate a EVM wallet from a given mnemonic.
      let generator = FGHDWalletUniGenerator.evm()
      let mnemonic = "xx xx..."
      let wallet = try generator.generate(from: mnemonic)
      
    • Batch wallets

      /// Solana ///
      let genCnt = 1000
      let generator = FGHDWalletUniGenerator.solana()
      
      // Randomly generate Solana wallets with 12 words mnemonic.
      let wallets = try await generator.batchGenerate(inCount: genCnt)
      
      // Specify the mnemonic words count(default is 12 words).
      let mnemonicSize = 
      let wallets = try await generator.batchGenerate(inCount: genCnt,
                                                      mnemonicSize: FGMnemonic24WordsSize.self)
                                                      
      // Generate Solana wallets given mnemonics.
      let mnemonics = ["xx", "yy"]
      let wallets = try await generator.batchGenerate(from: mnemonics)
      
      
      /// EVM ///
      
      let generator = FGHDWalletUniGenerator.evm()
      
      // Randomly generate EVM wallets with 12 words mnemonic.
      let wallets = try await generator.batchGenerate(inCount: genCnt)
      
      // Specify the mnemonic words count(default is 12 words).
      let mnemonicSize = 
      let wallets = try await generator.batchGenerate(inCount: genCnt,
                                                      mnemonicSize: FGMnemonic24WordsSize.self)
                                                      
      // Generate EVM wallets given mnemonics.
      let mnemonics = ["xx", "yy"]
      let wallets = try await generator.batchGenerate(from: mnemonics)
      
  • Multi-chain

    • Single wallet

      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure all handlers to generate wallets for the corresponding chains.
      let handlers = [FGHDGenHandler.solana(), FGHDGenHandler.evm(serviceSharedChains: evmSharedChains)]
      
      // Create a multi-chain tasks processor.
      let generator = FGMultiChainWalletProcessor(chainHandlers: handlers)
      
      // Generate with the operation kind: FGMultiChainHDWalletGenKind.
      //  - singleRandom(mnemonicSize:): Generate a single wallet by generating random mnemomic for each chain.
      //  - singleSpecific(mnemomic:): Generate a single wallet by using a given mnemomic for each chain
      //  - batchRandom(count:, mnemonicSize:, isInterruptible:): Generate  the specific count of // wallets by using random mnemomics  for each chain.
      //  - batchSpecific(mnemomics:, isInterruptible:): Generate the specific count of  wallets by using the given mnemomics  for each chain.
      let walletMap = try await generator.process(with: .singleRandom())
      for (chainName, wallets) in walletMap {
         print("\(chainName):")
          for wallet in wallets {
              print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic)")
          }
      }
      
      /// Output ///
      Optimism:
      address:0x1…1, privKey:9…8
      Ethereum:
      address:0x1…1, privKey:9…8
      Base:
      address:0x1…1, privKey:9…8
      Solana:
      address:A…k, privKey:5…a
      
    • Batch wallets

      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure all handlers to generate wallets for the corresponding chains.
      let handlers = [FGNonHDGenHandler.solana(), FGNonHDGenHandler.evm(serviceSharedChains: evmSharedChains)]
      
      // Create a multi-chain tasks processor.
      let generator = FGMultiChainWalletProcessor(chainHandlers: handlers)
      let genCnt = 3
      // Use the operation kind of .batch(count:).
      let walletMap = try await generator.process(with: .batch(count: genCnt))
      for (chainName, wallets) in walletMap {
         print("\(chainName):")
          for wallet in wallets {
              print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic)")
          }
      }
      
      /// Output ///
      Optimism:
      address:0x1…1, privKey:9…8
      address:0x2…5, privKey:7...c
      address:0xf..9, privKey:c..5
      Ethereum:
      address:0x1…1, privKey:9…8
      address:0x2..5, privKey:7..c
      address:0xf..9, privKey:c..5
      Base:
      address:0x1…1, privKey:9…8
      address:0x2..5, privKey:7..c
      address:0xf..9, privKey:c..5
      Solana:
      address:A…k, privKey:5…a
      address:D…s, privKey:3…s
      address:G…5, privKey:M…u
      

Import

  • Single chain

    • Single wallet

      /// Solana
      let importer = FGHDWalletUniGenerator.solana()
      let importedWallet = try importer.importWallet(from: wallet.mnemonic ?? "")
      
      /// EVM
      let importer = FGHDWalletUniGenerator.evm()
      let importedWallet = try importer.importWallet(from: wallet.mnemonic ?? "")
      
    • Batch wallets

      /// Solana
      let importer = FGHDWalletUniGenerator.evm()
      let importedWallet = try importer.importWallets(from: wallet.mnemonic ?? "")
      
      /// EVM
      let importer = FGHDWalletUniImporter.evm()
      let importedWalltes = try await importer.importWallets(from: phrases)
      
  • Multi-chain

    • Single wallet

      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure the importing handler of each chain.
      let handlers = [FGHDImportHandler.solana(),
                      FGHDImportHandler.evm(serviceSharedChains: evmSharedChains)]
      let importer = FGMultiChainWalletProcessor(chainHandlers: handlers)
      
      let mnemomic = "xx yy cc ..."
      
      // Using single(mnemonic:) as the import operation kind.
      let genWalletsMap = try await importer.process(with: .singleSpecific(mnemomic: mnemomic))
      
      for (chainName, wallets) in walletMap {
         print("\(chainName):")
          for wallet in wallets {
              print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic)")
          }
      }
      
      /// Output ///
      Optimism:
      address:0x1…1, privKey:9…8
      Ethereum:
      address:0x1…1, privKey:9…8
      Base:
      address:0x1…1, privKey:9…8
      Solana:
      address:A…k, privKey:5…a
      
    • Batch wallets

      // Set up all needed EVM chains except Ethereum which will be contained by default.
      let evmSharedChains: [any FGChainDescribable.Type] = [FGBaseChain.self, FGOptimismChain.self]
      
      // Configure the importing handler of each chain.
      let handlers = [FGHDImportHandler.solana(),
                      FGHDImportHandler.evm(serviceSharedChains: evmSharedChains)]
      let importer = FGMultiChainWalletProcessor(chainHandlers: handlers)
      
      let mnemonics = ["mnemonic1", "mnemonic2", ... ,"mnemonicN"]
      
      // Using single(mnemonic:) as the import operation kind.
      let genWalletsMap = try await importer.process(with: .batch(mnemonics: mnemonics))
      
      for (chainName, wallets) in walletMap {
         print("\(chainName):")
          for wallet in wallets {
              print("address:\(wallet.address), privKey:\(wallet.privKey), mnemonic:\(wallet.mnemonic)")
          }
      }
      

Export

  • Pasteboard

    • Single wallet

       let importer = FGPasteboardExporter()
       let result = try await importer.export(wallet: wallet)
       if !result {
          // Execute the failure logic.
       }
      
    • Batch wallets

       let importer = FGPasteboardExporter()
       let result = try await importer.export(wallets: wallets)
       if !result {
          // Execute the failure logic.
       }
      

      Now, the FGPasteboardExporter only supports export 200 wallets and will throw a error if exceeds 200.

  • File

     // Not sepecify the file path to export. Internally will create automaticlly a file in the  //'Wallet_yyyyMMdd_HHmmss' name format if not set.
     let exporter = FGFileExporter()
     let isSuccess = try await exporter.export(wallet: wallet)
     
     // Sepecify the file path to export.
     let filePath = "A detailed path"
      let exporter = FGFileExporter(filePath: filePath)
     let isSuccess = try await exporter.export(wallet: wallet)
    

    The default max count of wallets that can be written at once is 100, if the total count of wallets to be exported exceeds this value, they will be written one by one, otherwise will be written in one time. It supports be sepecified by set the Initialization param singleWriteMaxCount, but should set a reasonable value to avoid OOM.

    let exporter = FGFileExporter(singleWriteMaxCount: 500)
    

Dependencies

About

Forging — A convenient Web3 wallet toolkit for easily generating, importing, and exporting single/batch HD & non-HD wallets. Pluggable design for any chain, with Solana + full EVM support out of the box.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages