Swiftpack.co - Package - lukereichold/arweave-swift

Arweave Client SDK for Swift

GitHub license SPM compatible Twitter

A lightweight Swift client for the Arweave blockchain, providing type safety for interacting with the Arweave API

Installation

To install via Swift Package Manager, add Arweave to your Package.swift file. Alternatively, add it to your Xcode project directly.

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/lukereichold/arweave-swift.git", from: "1.0.0")
    ],
    ...
)

Then import Arweave wherever you’d like to use it:

import Arweave

Demo

See the included demo app, which dynamically creates a Wallet object from an existing Arweave JWK keyfile and uses an iOS share extension to create and submit a new data transaction containing the data of a given page in Safari.

Usage

Wallets and Keys

Creating a Wallet from an existing JWK keyfile

guard let keyFileData = try? Data(contentsOf: keyFileUrl) else { return }

let wallet = Wallet(jwkFileData: keyFileData)

Get a wallet's public address

wallet.address
/// 1seRanklLU_1VTGkEk7P0xAwMJfA7owA1JHW5KyZKlY

Check wallet balance (async)

All wallet balances are returned using winston units.

wallet.balance { result in
    let balance: Amount = try? result.get()
}

Convert amounts between AR and winston units

var transferAmount = Amount(value: 1, unit: .AR)
let amtInWinston = transferAmount.converted(to: .winston)
XCTAssertEqual(amtInWinston.value, 1000000000000, accuracy: 0e-12) // ✅

transferAmount = Amount(value: 2, unit: .winston)
let amtInAR = transferAmount.converted(to: .AR)
XCTAssertEqual(amtInAR.value, 0.000000000002, accuracy: 0e-12) // ✅

Fetch the last transaction ID for a given wallet (async)

wallet.lastTransactionId { result in
    let lastTxId: TransactionId = try? result.get()
}

Transactions

Transactions are the building blocks of the Arweave permaweb. They can send AR between wallet addresses or store data on the Arweave network.

Create a Data Transaction

Data transactions are used to store data on the Arweave permaweb and can contain any arbitrary data.

let data = "<h1>Hello World!</h1>".data(using: .utf8)!
let transaction = Transaction(data: data)

Create a wallet-to-wallet Transaction

let targetAddress = Address(address: "someOtherWalletAddress")
let transferAmount = Amount(value: 500, unit: .winston)

let transaction = Transaction(amount: transferAmount, target: targetAddress)

Modifying an existing Transaction

Metadata can be optionally added to transactions through tags, these are simple key/value attributes that can be used to document the contents of a transaction or provide related data.

let tag = Tag(name: "myTag", value: "myValue")
transaction.tags.append(tag)

Signing and Submitting a Transaction

The data and wallet-to-wallet transaction initializers above simply create an unsigned Transaction object. To be submitted to the network, however, each Transaction must first be signed.

let signed: Transaction = try transaction.sign(with: wallet)

try signed.commit { committedTxResult in
    switch committedTxResult {
    case .success:
        // Tx submitted successfully
    case .failure(error):
        // Handle error appropriately
    }
}

⚠️ Modifying a transaction object after signing it will invalidate the signature, this will cause it to be rejected by the network if submitted in that state. Transaction prices are based on the size of the data field, so modifying the data field after a transaction has been created isn't recommended as you'll need to manually update the price.

The transaction ID is a hash of the transaction signature, so a transaction ID can't be known until its contents are finalized and it has been signed.

Get a Transaction status (async)

Transaction.status(of: exampleTxId) { result in
    let status: Transaction.Status = try? result.get()

    /// Arweave.Transaction.Status.accepted(data: Arweave.Transaction.Status.Data(block_height: 502761, block_indep_hash: "V6pCKSyeQiqICWKM2G_zkQ8SCA_WKnZoVGOD8eKFV_xozoWS9xPFgncxnMWjtFao", number_of_confirmations: 8655))
}

Fetch Transaction content for a given ID (async)

Transaction.find(with: exampleTxId) { result in
    let tx: Transaction = try? result.get()
}

Fetch Transaction data (async)

We can get the transaction data (represented as a base64 URL encoded string) for a given transaction ID without having to fetch the entire Transaction object.

Transaction.data(for: lastTx!) { result in
    guard let dataString = try? result.get() else { return }
    let data = Data(base64URLEncoded: dataString)
}

Contribute

Contributions welcome. Please check out the issues.

Github

link
Stars: 6

Used By

Total: 0

Releases

1.0.2 - 2020-08-21 06:05:23

1.0.1 - 2020-08-21 05:49:25

Initial release - 2020-08-21 02:25:40