Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/frol/near-connect-ios/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This guide shows you how to call smart contract functions on NEAR using the iOS SDK. You’ll learn how to pass JSON arguments, attach NEAR deposits, and handle the results.
This code is extracted from the working MessageSigningDemoView in the NEAR Connect iOS example app.

Complete Contract Call Example

import SwiftUI
import NEARConnect

struct MessageSigningDemoView: View {
    @EnvironmentObject var walletManager: NEARWalletManager
    @Environment(\.dismiss) private var dismiss
    var onLog: ((_ action: String, _ params: String, _ output: String, _ isError: Bool) -> Void)?

    @State private var contractId = "guest-book.near"
    @State private var methodName = "add_message"
    @State private var argsText = "{\"text\": \"Hello from iOS!\"}"
    @State private var deposit = "0"
    @State private var isProcessing = false
    @State private var showError = false
    @State private var errorMessage = ""

    var body: some View {
        NavigationView {
            Form {
                Section {
                    Text("Call a smart contract function on NEAR")
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                }

                Section(header: Text("Contract Call")) {
                    HStack {
                        Text("Signer")
                            .foregroundColor(.secondary)
                        Spacer()
                        Text(walletManager.currentAccount?.accountId ?? "")
                            .font(.caption)
                    }

                    TextField("Contract ID", text: $contractId)
                        .textInputAutocapitalization(.never)
                        .autocorrectionDisabled()

                    TextField("Method Name", text: $methodName)
                        .textInputAutocapitalization(.never)
                        .autocorrectionDisabled()

                    VStack(alignment: .leading, spacing: 4) {
                        Text("Arguments (JSON)")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        TextEditor(text: $argsText)
                            .font(.system(.body, design: .monospaced))
                            .frame(height: 80)
                    }

                    HStack {
                        TextField("Deposit", text: $deposit)
                            .keyboardType(.decimalPad)
                        Text("NEAR")
                            .foregroundColor(.secondary)
                    }
                }

                Section {
                    Button(action: callContract) {
                        HStack {
                            Spacer()
                            if isProcessing {
                                ProgressView()
                                    .padding(.trailing, 8)
                            }
                            Text(isProcessing ? "Calling..." : "Call Contract")
                            Spacer()
                        }
                    }
                    .disabled(isProcessing || contractId.isEmpty || methodName.isEmpty)
                }

            }
            .navigationTitle("Call Contract")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Done") { dismiss() }
                        .disabled(isProcessing)
                }
            }
            .alert("Error", isPresented: $showError) {
                Button("OK", role: .cancel) { }
            } message: {
                Text(errorMessage)
            }
        }
    }

    private func callContract() {
        guard let argsData = argsText.data(using: .utf8),
              let args = try? JSONSerialization.jsonObject(with: argsData) as? [String: Any] else {
            errorMessage = "Invalid JSON arguments"
            showError = true
            return
        }

        let depositYocto = NEARWalletManager.toYoctoNEAR(deposit) ?? "0"
        let params = "contract: \(contractId), method: \(methodName), args: \(argsText), deposit: \(deposit) NEAR"

        Task {
            isProcessing = true
            defer { isProcessing = false }

            do {
                let txResult = try await walletManager.callFunction(
                    contractId: contractId,
                    methodName: methodName,
                    args: args,
                    deposit: depositYocto
                )
                let hashes = txResult.transactionHashes.joined(separator: ", ")
                onLog?("callFunction", params, "Hashes: \(hashes)", false)
            } catch {
                onLog?("callFunction", params, error.localizedDescription, true)
                errorMessage = error.localizedDescription
                showError = true
            }
        }
    }
}

Step-by-Step Breakdown

1
Define Contract Parameters
2
@State private var contractId = "guest-book.near"
@State private var methodName = "add_message"
@State private var argsText = "{\"text\": \"Hello from iOS!\"}"
@State private var deposit = "0"
3
Set up state variables for the contract ID, method name, JSON arguments, and optional NEAR deposit.
4
Parse JSON Arguments
5
guard let argsData = argsText.data(using: .utf8),
      let args = try? JSONSerialization.jsonObject(with: argsData) as? [String: Any] else {
    errorMessage = "Invalid JSON arguments"
    showError = true
    return
}
6
Arguments must be valid JSON that can be parsed into a [String: Any] dictionary. The SDK serializes this to the format expected by NEAR smart contracts.
7
Convert Deposit Amount
8
let depositYocto = NEARWalletManager.toYoctoNEAR(deposit) ?? "0"
9
Convert the NEAR deposit amount to yoctoNEAR. If no deposit is needed, use “0”.
10
Call the Contract Function
11
let txResult = try await walletManager.callFunction(
    contractId: contractId,
    methodName: methodName,
    args: args,
    deposit: depositYocto
)
12
Make the contract call with all parameters. This triggers the wallet UI for approval.
13
Handle the Result
14
let hashes = txResult.transactionHashes.joined(separator: ", ")
print("Transaction hashes: \(hashes)")
15
Extract transaction hashes from the result to track or verify the transaction.

API Reference

func callFunction(
    contractId: String,
    methodName: String,
    args: [String: Any],
    deposit: String = "0",
    gas: String? = nil
) async throws -> TransactionResult
Calls a smart contract function.Parameters:
  • contractId: The contract account ID (e.g., “guest-book.near”)
  • methodName: The function name to call (e.g., “add_message”)
  • args: JSON-serializable dictionary of arguments
  • deposit: Amount in yoctoNEAR to attach (default “0”)
  • gas: Optional gas limit in yoctoNEAR (defaults to 30 TGas)
Returns:
  • TransactionResult with transaction hashes
Throws:
  • Error if transaction fails or user cancels

Real-World Examples

Guest Book Contract

// Add a message to the guest book
let result = try await walletManager.callFunction(
    contractId: "guest-book.near",
    methodName: "add_message",
    args: [
        "text": "Hello from iOS!"
    ],
    deposit: "0"
)

NFT Minting

// Mint an NFT
let depositYocto = NEARWalletManager.toYoctoNEAR("0.01") ?? "0"

let result = try await walletManager.callFunction(
    contractId: "nft-contract.near",
    methodName: "nft_mint",
    args: [
        "token_id": "unique-token-\(UUID().uuidString)",
        "receiver_id": walletManager.currentAccount?.accountId ?? "",
        "metadata": [
            "title": "My NFT",
            "description": "Minted from iOS",
            "media": "https://example.com/image.png"
        ]
    ],
    deposit: depositYocto
)

Storage Deposit

// Register account for fungible token
let storageDeposit = NEARWalletManager.toYoctoNEAR("0.00125") ?? "0"

let result = try await walletManager.callFunction(
    contractId: "token.near",
    methodName: "storage_deposit",
    args: [
        "account_id": walletManager.currentAccount?.accountId ?? ""
    ],
    deposit: storageDeposit
)

Batch Operations

// Transfer multiple NFTs
let result = try await walletManager.callFunction(
    contractId: "nft.near",
    methodName: "nft_batch_transfer",
    args: [
        "token_ids": ["token1", "token2", "token3"],
        "receiver_id": "bob.near"
    ],
    deposit: "1" // 1 yoctoNEAR for security
)

User Flow

1

User enters contract details

The form collects contract ID, method name, arguments, and optional deposit.
2

App validates JSON arguments

Arguments are parsed to ensure they’re valid JSON before making the call.
3

User taps Call Contract

The callFunction method is invoked, triggering the wallet UI.
4

Wallet shows transaction preview

The WalletBridgeSheet displays the contract call details for user approval.
5

User approves transaction

The wallet signs and broadcasts the contract call transaction.
6

App receives transaction result

Transaction hashes are returned and can be used to track the call on-chain.
Test your contract calls on testnet first! Change the network configuration and use testnet contract addresses to avoid losing real NEAR tokens.

Error Handling

private func callContract() async {
    // Validate JSON
    guard let argsData = argsText.data(using: .utf8),
          let args = try? JSONSerialization.jsonObject(with: argsData) as? [String: Any] else {
        showError("Invalid JSON arguments")
        return
    }
    
    // Validate contract ID
    guard !contractId.isEmpty else {
        showError("Contract ID is required")
        return
    }
    
    // Validate method name
    guard !methodName.isEmpty else {
        showError("Method name is required")
        return
    }
    
    do {
        let depositYocto = NEARWalletManager.toYoctoNEAR(deposit) ?? "0"
        let result = try await walletManager.callFunction(
            contractId: contractId,
            methodName: methodName,
            args: args,
            deposit: depositYocto
        )
        print("Success: \(result.transactionHashes)")
    } catch {
        showError(error.localizedDescription)
    }
}

private func showError(_ message: String) {
    errorMessage = message
    showError = true
}

Next Steps

Authentication

Learn connect and sign message patterns

Token Transfer

Send NEAR tokens between accounts

View Methods

Query contract state without transactions

Error Handling

Handle contract call errors

Build docs developers (and LLMs) love