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
Define Contract Parameters
@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"
Set up state variables for the contract ID, method name, JSON arguments, and optional NEAR deposit.
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
}
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.
let depositYocto = NEARWalletManager. toYoctoNEAR (deposit) ?? "0"
Convert the NEAR deposit amount to yoctoNEAR. If no deposit is needed, use “0”.
Call the Contract Function
let txResult = try await walletManager. callFunction (
contractId : contractId,
methodName : methodName,
args : args,
deposit : depositYocto
)
Make the contract call with all parameters. This triggers the wallet UI for approval.
let hashes = txResult. transactionHashes . joined ( separator : ", " )
print ( "Transaction hashes: \( hashes ) " )
Extract transaction hashes from the result to track or verify the transaction.
API Reference
callFunction
Arguments Format
Deposits
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
Arguments must be a Swift dictionary that can be converted to JSON: // Simple arguments
let args: [ String : Any ] = [
"text" : "Hello, NEAR!"
]
// Complex arguments
let args: [ String : Any ] = [
"receiver_id" : "alice.near" ,
"amount" : "1000000000000000000000000" ,
"metadata" : [
"title" : "NFT Title" ,
"description" : "NFT Description"
]
]
// Array arguments
let args: [ String : Any ] = [
"account_ids" : [ "alice.near" , "bob.near" ],
"amounts" : [ 100 , 200 , 300 ]
]
Use Swift’s native types (String, Int, Bool, Array, Dictionary) - they’ll be automatically converted to the correct JSON format.
Some contract methods require attaching NEAR tokens: // No deposit (read-only or free method)
let result = try await walletManager. callFunction (
contractId : "contract.near" ,
methodName : "get_data" ,
args : [ : ],
deposit : "0"
)
// With deposit (e.g., storage staking)
let depositYocto = NEARWalletManager. toYoctoNEAR ( "0.1" ) ?? "0"
let result = try await walletManager. callFunction (
contractId : "contract.near" ,
methodName : "register_account" ,
args : [ : ],
deposit : depositYocto
)
Always check the contract’s documentation to see if a deposit is required. Storage deposits typically range from 0.00125 to 0.1 NEAR.
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
User enters contract details
The form collects contract ID, method name, arguments, and optional deposit.
App validates JSON arguments
Arguments are parsed to ensure they’re valid JSON before making the call.
User taps Call Contract
The callFunction method is invoked, triggering the wallet UI.
Wallet shows transaction preview
The WalletBridgeSheet displays the contract call details for user approval.
User approves transaction
The wallet signs and broadcasts the contract call transaction.
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