https://github.com/cellact/Arnacon-iOS-SDK.git Product: iArnacon Platforms: iOS 13+, macOS 10.15+ Dependencies the package already pulls: web3swift, BlueECC No CocoaPods. Do not add cellact/arnacon-swift — that is the store app.
iOS · Swift
Add iArnacon, implement three persistence methods, connect the network, then message and ring an identity. No API key. No CocoaPods.
In Xcode: File → Add Package Dependencies. Add the iOS SDK repository, not the store app.
https://github.com/cellact/Arnacon-iOS-SDK.git Product: iArnacon Platforms: iOS 13+, macOS 10.15+ Dependencies the package already pulls: web3swift, BlueECC No CocoaPods. Do not add cellact/arnacon-swift — that is the store app.
The repository is not on the public package index. If GitHub returns 404, you do not have access yet. A private clone still works as a local package path.
The SDK does not own disk or HTTP. You implement three protocols. The store app wires UserDefaults and the shipped CloudFunctions server.
PDataSaver is three methods. The protocol extension on top of them stores the wallet, products, and tokens. Implement the three; do not reimplement the extension.
import iArnacon
final class AppDataSaver: PDataSaver {
private let defaults = UserDefaults.standard
func setPreference(key: String, value: String) {
defaults.set(value, forKey: key)
}
func getPreference(key: String, defaultValue: String?) -> String? {
defaults.string(forKey: key) ?? defaultValue
}
func resetPreferences() {
guard let domain = Bundle.main.bundleIdentifier else { return }
defaults.removePersistentDomain(forName: domain)
}
}
PLogger is debug(_:) and error(_:). PServer is the backend surface. Use the shipped CloudFunctions unless you are replacing the entire backend. You do not write URL lists by hand — CloudFunctions loads them from on-chain config.
Create the SDK, set a logger, then connect the network. Blockchain calls fail or return nil until setNetworkSettings finishes.
gpsCoordinates is the local encryption password for the wallet secrets. It is not a location and not a phone number. The store app currently passes "123". Use a secret your app already stores, and never log it.
import iArnacon
let dataSaver = AppDataSaver()
let arnacon = Arnacon(
dataSaveHelper: dataSaver,
gpsCoordinates: storedEncryptionPassword
)
arnacon.setLogger(AppLogger())
let server = await CloudFunctions()
let appVersion = Bundle.main.infoDictionary?["AppStoreVersion"] as? String
?? "1.0.0"
await arnacon.setNetworkSettings(server, appVersion, false)
The third argument is forceFresh. The store app passes false so contract addresses are not refetched on every launch. Pass true only when you intend to refresh.
People talk as an email they verify, or as a new identity they install. Recipients look like alice.arnacon.global. A phone number is not the gate.
let me = arnacon.getMainCoordinates()
let owner = try await arnacon.getENSOwner(
memberName: "alice.arnacon.global"
)
let xData = arnacon.getXData(identity: "alice.arnacon.global")
let xSign = try arnacon.getXSign(xData)
let signed = try arnacon.signMessage(message)
Never log the mnemonic, the encryption password, or the private key. installProduct adds an identity. New code must wait for an explicit user Allow. Do not auto-run it from a push payload.
Prepare, then execute. NotificationType.message = 1. Do not treat a plaintext helper as the entry if you need to inspect the plan.
let prepared = await arnacon.prepareNotification(
sender: "alice.arnacon.global",
target: "bob.arnacon.global",
message: "Hello from Alice",
notificationType: .message
)
let result = await arnacon.executeNotification(prepared)
// or one step:
let sent = await arnacon.sendNotification(
sender: "alice.arnacon.global",
target: "bob.arnacon.global",
message: "Hello from Alice",
notificationType: .message
)
Encrypted chat content is a separate path: encryptMessageForRecipient then sendDirectMessage. The store app uses that for the chat body. The notification plan is what wakes the other device.
Ring the other identity. NotificationType.call = 0. CallKit lives in your app, not in this SDK.
let ringing = try await arnacon.sendCallNotification(
sender: "alice.arnacon.global",
target: "bob.arnacon.global"
)
// or the plan path:
let prepared = await arnacon.prepareNotification(
sender: "alice.arnacon.global",
target: "bob.arnacon.global",
message: "{\"type\":\"call\"}",
notificationType: .call
)
let result = await arnacon.executeNotification(prepared)
SDP, ICE, cancel, reject, and end are not incoming-call invites. Use NotificationType.realtimeSignal for those so the other phone does not ring again.
Register this device so it can ring. Do not upload tokens for someone else.
try await arnacon.sendNotiTokens(fcmToken, voipToken)
VoIP push and CallKit reporting stay in the host app. The SDK only stores and routes the tokens.
installProductgpsCoordinates / the encryption passwordNext