JavaScript# Installation# To interact with the Ethereum blockchain, you can use either ethers.js
or web3.js
libraries with Magic.
Ethers.js# Copy npm install --save ethers
Web3.js# Initializing Provider# Ethereum provider is only supported in magic-sdk@1.0.1 or later versions.
Ethers.js# ES Modules/TypeScript CommonJS Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
Web3.js# ES Modules/TypeScript CommonJS Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
Use Different Networks# Choose Different Testnet# Copy const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' , {
network : 'ropsten' ,
} )
Configure Custom Nodes# Copy const customNodeOptions = {
rpcUrl : 'http://127.0.0.1:7545' ,
chainId : 1011 ,
}
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' , {
network : customNodeOptions ,
} )
Get User Info# Ethers.js# Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const address = await signer . getAddress ( )
const balance = ethers . utils . formatEther (
await provider . getBalance ( userAddress )
)
Web3.js# Example is using web3@1.2.0 or later version.
Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const address = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const balance = web3 . utils . fromWei (
await web3 . eth . getBalance ( address )
)
Send Transaction# Ethers.js# Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D'
const amount = ethers . utils . parseEther ( '1.0' )
const tx = await signer . sendTransaction ( {
to : destination ,
value : amount ,
} )
const receipt = await tx . wait ( )
Web3.js# Example is using web3@1.2.0 or later version.
Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const fromAddress = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D'
const amount = web3 . utils . toWei ( 1 )
const receipt = await web3 . eth . sendTransaction ( {
from : fromAddress ,
to : destination ,
value : amount ,
} )
Sign Message# Ethers.js# Personal Sign Sign Typed Data v1 Sign Typed Data v3 Sign Typed Data v4 Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const originalMessage = 'YOUR_MESSAGE'
const signedMessage = await signer . signMessage ( originalMessage )
Web3.js# The following examples assume web3@>=1.2.0
Personal Sign Sign Typed Data v1 Sign Typed Data v3 Sign Typed Data v4 Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const fromAddress = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const originalMessage = 'YOUR_MESSAGE'
const signedMessage = await web3 . eth . personal . sign ( originalMessage , fromAddress )
Smart Contract# Solidity Contract# In this example, we'll be demonstrating how to use Magic with ethers.js or web3.js to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.
Copy pragma solidity ^ 0.5 .10 ;
contract HelloWorld {
string public message ;
constructor ( string memory initMessage ) public {
message = initMessage ;
}
function update ( string memory newMessage ) public {
message = newMessage ;
}
}
Ethers.js# Deploy Contract# Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractByteCode =
'0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032'
const contractFactory = new ethers . ContractFactory (
contractABI ,
contractByteCode ,
signer
)
const contract = await contractFactory . deploy ( 'Hello World!' )
const receipt = await contract . deployed ( )
Read From Contract# Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'
const contract = new ethers . Contract ( contractAddress , contractABI , signer )
const message = await contract . message ( )
Write to Contract# Copy import { Magic } from 'magic-sdk'
import { ethers } from 'ethers'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const provider = new ethers . providers . Web3Provider ( magic . rpcProvider )
const signer = provider . getSigner ( )
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'
const contract = new ethers . Contract ( contractAddress , contractABI , signer )
const tx = await contract . update ( 'NEW_MESSAGE' )
const receipt = await tx . wait ( )
Web3.js# Example is using web3@1.2.0 or later version.
Deploy Contract# Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const fromAddress = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractByteCode =
'0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032'
const contract = new web3 . eth . Contract ( JSON . parse ( contractABI ) )
const contractInstance = await contract
. deploy ( {
data : contractByteCode ,
arguments : [ 'Hello World!' ] ,
} )
. send ( {
from : fromAddress ,
} )
Read From Contract# Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const fromAddress = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'
const contract = new web3 . eth . Contract ( JSON . parse ( contractABI ) , contractAddress )
const message = await contract . methods . message ( ) . call ( )
Write to Contract# Copy import { Magic } from 'magic-sdk'
import Web3 from 'web3'
const magic = new Magic ( 'YOUR_PUBLISHABLE_API_KEY' )
const web3 = new Web3 ( magic . rpcProvider )
const fromAddress = ( await web3 . eth . getAccounts ( ) ) [ 0 ]
const contractABI =
'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]'
const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'
const contract = new web3 . eth . Contract ( JSON . parse ( contractABI ) , contractAddress )
const receipt = await contract . methods
. update ( 'NEW_MESSAGE' )
. send ( { from : fromAddress } )
iOS# Installation# To interact with the Ethereum blockchain, Magic iOS SDK embeds Web3.swift
as sub dependency. No more extra dependency is needed.
Initializing Provider# Following example is using Swift 5 with XCode 11. IOS demo will be open-sourced soon.
Copy // AppDelegate.swift
import MagicSDK
import UIKit
@UIApplicationMain
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// assign the newly created Magic instance to shared property
// Test key defaults to "rinkeby", live key defaults to "mainnet"
Magic.shared = Magic("YOUR_PUBLISHABLE_API_KEY");
return true
}
Copy // ViewController.swift
import UIKit
import MagicSDK
import MagicSDK_Web3
class Web3ViewController: UIViewController {
let web3 = Web3(provider: Magic.shared.rpcProvider)
}
Use Different Networks# Choose Different Testnet# Copy // AppDelegate.swift
import MagicSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// assign to Magic singleton
Magic.shared = Magic("YOUR_PUBLISHABLE_API_KEY", EthNetwork.rinkeby);
return true
}
Configure Custom Nodes# Copy // AppDelegate.swift
import MagicSDK
// assign to Magic singleton
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let config = CustomNodeConfiguration(rpcUrl: "https://alchemy.io", chainId: 1)
Magic.shared = Magic(apiKey: "API_KEY", customNode: config);
return true
}
Do not set the custom nodes to local IP address (E.x. "http://127.0.0.1" ). Local IP will point to the network environment inside mobile device / simulator
Associated Class# CustomNodeConfiguration(rpcUrl: String, chainId: Int?)
rpcUrl
:Your own node URLchainId
: Your own node's chainIdEthNetwork
Copy public enum EthNetwork: String {
case mainnet
case kovan
case rinkeby
case ropsten
}
Get User Info# Copy import MagicSDK
import MagicSDK_Web3
import PromiseKit
class Web3ViewController: UIViewController {
var web3 = Web3(provider: Magic.shared.rpcProvider)
// ⭐️ After user is successfully authenticated
@IBOutlet weak var accountLabel: UILabel!
func getAccount() {
firstly {
// Get user's Ethereum public address
web3.eth.accounts()
}.done { accounts -> Void in
if let account = accounts.first {
// Set to UILa
self.accountLabel.text = account.hex(eip55: false)
} else {
print("No Account Found")
}
}.catch { error in
print("Error loading accounts and balance: \(error)")
}
}
}
Send Transaction# Copy import MagicSDK
import MagicSDK_Web3
class Web3ViewController: UIViewController {
var web3 = Web3(provider: Magic.shared.rpcProvider)
var account: EthereumAddress?
// ⭐️ After user is successfully authenticated
func sendTransaction() {
guard let account = self.account else { return }
// Construct a transaction
let transaction = EthereumTransaction(
from: account, // from Get User Info section
to: EthereumAddress(hexString: "0xE0cef4417a772512E6C95cEf366403839b0D6D6D"),
value: EthereumQuantity(quantity: 1.gwei)
)
// Submit transaction to the blockchain
web3.eth.sendTransaction(transaction: transaction).done { (transactionHash) in
print(transactionHash.hex())
}.catch { error in
print(error.localizedDescription)
}
}
}
Sign Message# Magic iOS SDK extends the functionality from Web3.swift to allow developers to sign Typed Data. Make sure to import MagicSDK
while using these functions.
Eth Sign Sign Typed Data Legacy (V1) Sign Typed Data (EIP 712) Copy import MagicSDK
import MagicSDK_Web3
import PromiseKit
class ViewController: UIViewController {
let web3 = Web3(provider: Magic.shared.rpcProvider)
var account: EthereumAddress?
func ethSign() {
guard let account = self.account else { return }
let message = try! EthereumData("Hello World".data(using: .utf8)!)
web3.eth.sign(from: account, message: message).done({ result in
print(result.hex())
})
}
}
Smart Contract# In this example, we'll be demonstrating how to use Magic with Web3.swift to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.
Copy pragma solidity ^ 0.5 .10 ;
contract HelloWorld {
string public message ;
constructor ( string memory initMessage ) public {
message = initMessage ;
}
function update ( string memory newMessage ) public {
message = newMessage ;
}
}
Deploy Contract# Copy import MagicSDK
import MagicSDK_Web3
class Web3ViewController: UIViewController {
let web3 = Web3(provider: Magic.shared.rpcProvider)
var account: EthereumAddress?
// ⭐️ After user is successfully authenticated
func deployContract() {
guard let account = self.account else { return }
do {
let contractABI = """
[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
""".data(using: .utf8)!
let contractByteCode = try EthereumData("0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032")
/// Create Contract instance
let contract = try web3.eth.Contract(json: contractABI, abiKey: nil, address: nil)
/// Deploy contract
guard let invocation = contract.deploy(byteCode: contractByteCode) else { return }
invocation.send(from: self.account!, gas: 1025256, gasPrice: 0) { (hash, error) in
print(hash?.hex() ?? "Missing Hash")
print(error?.localizedDescription ?? "Error")
}
} catch {
print(error.localizedDescription)
}
}
}
Read From Contract# Copy import MagicSDK
import MagicSDK_Web3
class MagicViewController: UIViewController {
let web3 = Web3(provider: Magic.shared.rpcProvider)
var account: EthereumAddress?
// ⭐️ After user is successfully authenticated
func getMessage() {
do {
/// Construct contract instance
let contractABI = """
[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
""".data(using: .utf8)!
let contract = try web3.eth.Contract(json: contractABI, abiKey: nil, address: EthereumAddress(ethereumValue: "0x8b211dfebf490a648f6de859dfbed61fa22f35e0"))
/// contract call
contract["message"]?().call() { response, error in
if let response = response, let message = response[""] as? String {
print(message.description)
} else {
print(error?.localizedDescription ?? "Failed to get response")
}
}
} catch {
/// Error handling
print(error.localizedDescription)
}
}
}
Write to Contract# Copy import MagicSDK
import MagicSDK_Web3
class MagicViewController: UIViewController {
let web3 = Web3(provider: Magic.shared.rpcProvider)
var account: EthereumAddress?
// ⭐️ After user is successfully authenticated
func writeMessage() {
guard let account = self.account else { return }
do {
/// contract instance
let contractABI = """
[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
""".data(using: .utf8)!
let contract = try web3.eth.Contract(json: contractABI, abiKey: nil, address: EthereumAddress(ethereumValue: "0x8b211dfebf490a648f6de859dfbed61fa22f35e0"))
/// contract call
guard let transaction = contract["update"]?("NEW_MESSAGE").createTransaction(
nonce: 0,
from: account,
value: 0,
gas: EthereumQuantity(150000),
gasPrice: EthereumQuantity(quantity: 21.gwei)
) else { return }
web3.eth.sendTransaction(transaction: transaction).done({ txHash in
print(txHash.hex())
}).catch{ error in
print(error.localizedDescription)
}
} catch {
print(error.localizedDescription)
}
}
}
Android# Installation# To interact with the Ethereum blockchain, Magic Android SDK integrates Web3j
as sub dependency.
Add the following dependencies in build.gradle
Copy dependencies {
implementation 'link.magic:magic-android:0.3.0'
implementation 'org.web3j:core:4.6.0-android' // Not required
implementation 'org.web3j:geth:4.6.0-android' // Only for personal Sign
}
Initializing Provider# The following example is using Kotlin 1.3 . Android demo will be open-sourced soon. You may use Android Studio to convert Java to Kotlin or vice versa.
Copy class MagicActivity: AppCompatActivity() {
lateinit var magic: Magic
lateinit var web3j: Web3j
lateinit var gethWeb3j: Geth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY")
web3j = Web3j.build(magic.rpcProvider)
gethWeb3j = Geth.build(magic.rpcProvider)
}
}
Use Different Networks# Choose Different Testnet# Copy magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY", Magic.Network.Mainnet)
Configure Custom Nodes# Copy magic = Magic(this, "##YOUR_PUBLISHABLE_API_KEY", CustomNodeConfiguration("https://alchemy.io"))
Do not set the custom nodes to local IP address (E.x. "http://127.0.0.1"\ ), because local IP will point to the network environment inside mobile device / simulator. Try accessible IP address in the same Wifi/Internet Environment (E.x. "http://10.0.0.93:3000"\ )
Associated Class# CustomNodeConfiguration(rpcUrl: String, chainId: Int?)
rpcUrl
:Your own node URLchainId
: Your own node's chainIdMagic.EthNetwork
Copy enum class EthNetwork {
Mainnet, Kovan, Rinkeby, Ropsten
}
Get User Info# Copy class MagicActivity: AppCompatActivity() {
lateinit var magic: Magic
lateinit var web3j: Web3j
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY")
web3j = Web3j.build(magic.rpcProvider)
}
// ⭐️ After user is successfully authenticated
fun getAccount(){
try {
val accounts = web3j.ethAccounts().sendAsync()
accounts.whenComplete { accRepsonse: EthAccounts?, error: Throwable? ->
if (error != null) {
Log.e("MagicError", error.localizedMessage)
}
if (accRepsonse != null && !accRepsonse.hasError()) {
account = accRepsonse.accounts[0]
Log.d("Magic", "Your address is $account")
}
}
} catch (e: Exception) {
Log.e("Error", e.localizedMessage)
}
}
}
Send Transaction# Copy class MagicActivity: AppCompatActivity() {
lateinit var magic: Magic
lateinit var web3j: Web3j
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY")
web3j = Web3j.build(magic.rpcProvider)
}
// ⭐️ After user is successfully authenticated
fun sendTransaction(v: View) {
try {
val value: BigInteger = Convert.toWei("0.5", Convert.Unit.ETHER).toBigInteger()
val transaction = createEtherTransaction(account, BigInteger("1"), BigInteger("21000"), BigInteger("21000"), account, value)
val receipt = web3j.ethSendTransaction(transaction).send()
Log.d("Transaction complete: " + receipt.transactionHash)
} catch (e: Exception) {
Log.e("Error", e.localizedMessage)
}
}
}
Sign Message# Magic Android SDK extends the functionality from Web3j to allow developers to sign Typed Data. You may find it in magic.web3jSigExt
Personal Sign Sign TypedData Legacy (V1) Sign Typed Data v3 Sign Typed Data v4 Copy class MagicActivity: AppCompatActivity() {
lateinit var magic: Magic
lateinit var web3j: Web3j
lateinit var gethWeb3j: Geth
// ⭐️ After user is successfully authenticated
private var account: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY")
web3j = Web3j.build(magic.rpcProvider)
gethWeb3j = Geth.build(magic.rpcProvider)
}
fun personSign(view: View) {
val message = "Hello from Magic!!!"
val personalSign: PersonalSign = gethWeb3j.personalSign(
message, account, "password")
.send()
Log.d("Magic", "Signed Message: " + personalSign.signedMessage)
// Recover Message
val recovered = gethWeb3j.personalEcRecover(message, personalSign.signedMessage).send()
Log.d("Magic", "Recovered Address: " + recovered.recoverAccountId)
}
}
Smart Contract# Solidity Contract# In this example, we'll be demonstrating how to use Magic with Web3j to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.
Copy pragma solidity ^ 0.5 .10 ;
contract HelloWorld {
string public message ;
constructor ( string memory initMessage ) public {
message = initMessage ;
}
function update ( string memory newMessage ) public {
message = newMessage ;
}
}
Create a Kotlin/Java Contract Class from ABI# Web3j supports the auto-generation of smart contract function wrappers in Java from Solidity ABI files.
To get started, you must have two files
ABI JSON file <Contract>.json
ByteCode file <Contract>.bin
Install web3j cli-tool# Copy $ curl -L https://get.web3j.io | sh
You may need to install a JDK to support this library
After it has been installed to your computer, you may run the following command to check
Create the contract class# Copy $ web3j solidity generate -a = ./path/to/ < Contract > .json -b = ./path/to/ < Contract > .bin -o = /output/path/ -p = { packageName }
You’ll find a Contract.java
file created in your output directory above. Put this file in your project, and no more changes are needed.
For more detail about this section. Please check the following link
http://docs.web3j.io/latest/smart_contracts/construction_and_deployment/#solidity-smart-contract-wrappers
Contract Functions# When deploying contract or building contract using web3j library, Magic offers MagicTxnManager
class as a default TransactionManager
that helps you to avoid dealing with private keys or credentials that Contract class requires.
Deploy Contract# Copy import link.magic.demo.contract.Contract // This is the contract class you created above
class MagicActivity: AppCompatActivity() {
lateinit var magic: Magic
lateinit var web3j: Web3j
// ⭐️ After user is successfully authenticated
private var account: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
magic = Magic(this, "YOUR_PUBLISHABLE_API_KEY")
web3j = Web3j.build(magic.rpcProvider)
}
fun deployContract(view: View) {
try {
val price = BigInteger.valueOf(22000000000L)
val limit = BigInteger.valueOf(4300000)
val gasProvider = StaticGasProvider(price, limit)
val contract = Contract.deploy(
web3j,
account?.let { MagicTxnManager(web3j, it) },
gasProvider,
"HELLO_WORLD_FROM_ANDROID"
).send()
Log.d("Magic", "Deploy to" + contract.contractAddress)
} catch (e: Exception) {
Log.e("E", "error", e)
}
}
}
Read From Contract# Copy fun contractRead(view: View) {
try {
val price = BigInteger.valueOf(22000000000L)
val limit = BigInteger.valueOf(4300000)
val gasProvider = StaticGasProvider(price, limit)
// Contract in Rinkeby testnet
val contract = ExampleContract.load("0x6a2d321a3679b1b3c8a19b84e41abd11763a8ab5", web3j, account?.let { MagicTxnManager(web3j, it) }, gasProvider)
if (contract.isValid) {
val ethCall = contract.message().send()
Log.d("Magic", ethCall.toString())
} else {
throw Error("contract not valid")
}
} catch (e: Exception) {
Log.e("E", "error", e)
}
}
Write to Contract# Copy fun contractWrite(view: View) {
try {
val price = BigInteger.valueOf(22000000000L)
val limit = BigInteger.valueOf(4300000)
val gasProvider = StaticGasProvider(price, limit)
// Contract in Rinkeby testnet
val contract = ExampleContract.load("0x6a2d321a3679b1b3c8a19b84e41abd11763a8ab5", web3j, account?.let { MagicTxnManager(web3j, it) }, gasProvider)
if (contract.isValid) {
val ethCall = contract.update("NEW_MESSAGE_FROM_ANDROID").send()
Log.d("Magic", ethCall.toString())
} else {
throw Error("contract not valid")
}
} catch (e: Exception) {
Log.e("E", "error", e)
}
}