# Getting started

  1. Connect to the zkSync network.
  2. Deposit assets from Ethereum into zkSync.
  3. Make transfers.
  4. Withdraw funds back to Ethereum mainnet (or testnet).

# Adding zkSync Swift SDK as a dependency

# CocoaPods

pod 'ZKSync'

# Swift Package Manager

  1. In Xcode go to File -> Swift Packages -> Add Package Dependency....
  2. Insert https://github.com/zksync-sdk/zksync-swift.git in Enter package repository URL field and press Enter.
  3. In Rules set master as a default branch.

# Creating signers

Using seed bytes (like MNEMONIC phrase). Must have length >= 32

let zkSigner = try ZkSigner(seed: seed)

Using raw private key

let privateKey = Data(hex: "0x...")
let zkSigner = try ZkSigner(rawPrivateKey: privateKey)

Using EthSigner (explained below). The private key used by ZkSigner is implicitly derived from Ethereum signature of a special message.

let ethSigner = ...
let zkSigner = try ZkSigner(ethSigner: ethSigner, chainId: .goerli)

In case of interacting with Ethereum network like Deposit or onchain Withdraw and for creating ZkSigner you may need to create EthSigner.

let ethSigner = try DefaultEthSigner(privateKey: "0x...")

// or from Mnemonic
let ethSigner = try DefaultEthSigner(mnemonic: "some mnemonic phrase")

# Connecting to zkSync network

For interact with both zkSync and Ethereum networks you need to create providers with endpoints to blockchain nodes

# zkSync provider

Library has predefined URLs for the next networks ChainId.Mainnet,ChainId.Goerli that officially supports by MatterLabs. Also you can use local node for testing ChainId.Localhost set to http://127.0.0.1:3030

let provider = DefaultProvider(chainId: .goerli)

You can create Provider with any custom URL, just use HTTPTransport for DefaultProvider

let transport = HTTPTransport(networkURL: "http://127.0.0.1:3030")
let provider = DefaultProvider(transport: transport)

# Ethereum provider

For onchain operation in Ethereum network you may create EthereumProvider using method createEthereumProvider of Wallet

let wallet = ...
let ethereum = try wallet.createEthereumProvider(web3: Web3.InfuraGoerliWeb3())

# Creating a Wallet

To control your account in zkSync, use the Wallet. It can sign transactions with keys stored in ZkSigner and EthSigner and send transaction to zkSync network using Provider.

let ethSigner = ...
let zkSigner = ...
let wallet = try DefaultWallet(ethSigner: ethSigner, zkSigner: zkSigner, provider: DefaultProvider(chainId: .goerli))

For onchain operations you can create Ethereum provider from Wallet

let wallet = ...
let ethereum = try wallet.createEthereumProvider(web3: Web3.InfuraGoerliWeb3())

# Depositing assets from Ethereum into zkSync

Let's try to deposit 1.0 ETH to our zkSync account.

let ethSigner = ...
let ethereum = ...
let amount = Web3.Utils.parseToBigUInt("1", units: .eth)!
firstly {
    ethereum.deposit(token: .ETH, amount: amount, userAddress: self.ethSigner.address)
}.done { result in
    print("Successfully performed deposit with result: \(result)")
}.catch { error in
    print("Failed with error: \(error)")
}

# Checking your zkSync balance

You should be want to check your balance in zkSync network after deposit.

firstly {
    wallet.getAccountStatePromise()
}.done { (state) in
    let balance = state.committed.balances["ETH"] ?? "0"
    print("Balance: \(balance)")
}.catch { (error) in
    print("Failed with error: \(error)")
}

# Unlocking zkSync account

To make any transaction in zkSync network, you must register your ZkSigner's public key to your account provided EthSigner.

let wallet = ...

firstly {
    wallet.getAccountStatePromise()
}.then { state in
    wallet.provider
        .transactionFeePromise(for: .changePubKey, address: wallet.address, tokenIdentifier: Token.ETH.address)
        .map { ($0, state) }
}.then { (feeDetails, state) -> Promise<String> in
    let fee = TransactionFee(feeToken: Token.ETH.address,
                             fee: feeDetails.totalFeeInteger)
    return wallet.setSigningKeyPromise(fee: fee,
                                       nonce: state.committed.nonce,
                                       onchainAuth: false)
}.done { hash in
    print("Successfully submitted transaction with hash: \(hash)")
}.catch { error in
    print("Failed to submit transaction with error: \(error)")
}

# Making transfer funds in zkSync

Now after Deposit and Unlocking your account you can create second account and transfer some funds to it.

Note that we can send assets to any fresh Ethereum account, without preliminary registration!

We're going to transfer 0.1 ETH

let receiver = "0x..."
let wallet = ...
let amount = Web3.Utils.parseToBigUInt("1000000", units: .Gwei)!

firstly {
    wallet.getAccountStatePromise()
}.then { state in
    wallet.provider.transactionFeePromise(for: .transfer,
                                          address: receiver,
                                          tokenIdentifier: Token.ETH.address).map { ($0, state) }
}.then { (feeDetails, state) -> Promise<String> in
    let fee = TransactionFee(feeToken: Token.ETH.address,
                             fee: feeDetails.totalFeeInteger)
    return wallet.transferPromise(to: receiver,
                                  amount: amount,
                                  fee: fee,
                                  nonce: nil)
}.done { hash in
    print("Successfully submitted transaction with hash: \(hash)")
}.catch { error in
    print("Failed to submit transaction with error: \(error)")
}

# Withdrawing funds back to Ethereum

All (or part of) your funds can be withdrawn back to any yours account in Ethereum.

let wallet = ...
let amount = Web3.Utils.parseToBigUInt("1000", units: .Gwei)!

firstly {
    wallet.getAccountStatePromise()
}.then { state in
    wallet.provider.transactionFeePromise(for: .withdraw, address: wallet.address,
                                               tokenIdentifier: Token.ETH.address).map { ($0, state) }
}.then { (feeDetails, state) -> Promise<String> in
    let fee = TransactionFee(feeToken: Token.ETH.address,
                             fee: feeDetails.totalFeeInteger)
    return wallet.withdrawPromise(ethAddress: state.address,
                                  amount: amount,
                                  fee: fee,
                                  nonce: state.committed.nonce,
                                  fastProcessing: false)
}.done { hash in
    print("Successfully submitted transaction with hash: \(hash)")
}.catch { error in
    print("Failed to submit transaction with error: \(error)")
}