Portal offers SDKs for Web, iOS, Android, and React Native. To install the chosen Portal SDK in your app, simply add the Portal package to your project.
yarnadd@portal-hq/web
Using Swift Package Manager (SPM)
In Xcode, right-click on your project in the Project Navigator
The Portal SDK is initialized with a Client API Key or Client Session Token. You can get a test Client API Key from the Portal Admin Dashboard in the Settings -> Test Client API Keys section. Simply click the New + button.
A modal will then be presented, allowing you to copy your test Client API Key. You can repeat this process as many times as you need to.
Initializing Portal
To initialize Portal in your application, create a new instance of the Portal class included in the package dependency you added. You can provide your new test Client API Key as the apiKey argument during initialization. rpcConfig is a map of CAIP-2 Chain IDs to their respective RPC URLs.
Portal offers custom approval flows during the signing process, but for now, we can auto-approve all signatures with the autoApprove argument.
To create a new wallet you can use the createWallet() function. This function also offers an optional callback that can be provided to receive status updates during the MPC operation.
This function will create two wallets in the background, an EIP-155 wallet and a Solana wallet.
The Portal library has a Provider built-in, so signing transactions and making RPC calls is built into the library out-of-the-box. All of these actions can be handled by the request(chainId, method, params) function. The chainId will need to be a CAIP-2 compliant Chain ID.
For more info on Chain ID formatting, see this doc.
The return value of the request() function is largely dependent on the RPC method provided. In the case of signing a transaction, we can use the eth_sendTransaction RPC method for EVM (EIP-155) or the sol_signAndSendTransaction RPC method for Solana. This method will return a transaction hash.
Submitting an EVM Transaction
constchainId='eip155:11155111'// Use Sepolia testnet// Get your local EVM addressconstaddress=awaitportal.getEip155Address()// Build the transactionconsttransaction= { to:'0xRecipientAddress', value:BigNumber.from('1').toHexString(), gasPrice:'0x6000', from: address,}// Sign the transactionconsttxHash=awaitportal.request({ method:'eth_sendTransaction', params: [transaction],// RPC params are always expected to be an array chainId})console.log(`✅ Transaction hash: ${txHash}`)
let chainId ="eip155:11155111"// Use Sepolia testnet// Get your local Ethereum addressguardlet address =await portal.getAddress(chainId)else {// Handle a missing address herereturn}// Build the transactionlet transaction = ["from": address,"to":"0xRecipientAddress","value":"0x10", // Native token amount to send (WEI for eip155:11155111).]// Sign the transactionlet response =tryawait portal.request( chainId, withMethod: .eth_sendTransaction, andParams: [transaction] // RPC params are always expected to be an array)// Obtain the transaction hash.guardlet txHash = response.result as?Stringelse {// Handle a bad response herereturn}print("✅ Transaction hash: \(txHash)")
val chainId ="eip155:11155111"// Use Sepolia testnet// Get your local Ethereum addressval address = portal.getAddress(chainId)// Build the transactionval transaction =EthTransactionParam( from = address, to ="0xRecipientAddress", gas ="0x6000", gasPrice =null, maxFeePerGas =null, maxPriorityFeePerGas =null,value="0x${BigInteger("1").toString(16)}",data="",)// Sign the transactionval response = portal.request( chainId, PortalRequestMethod.eth_sendTransaction, listOf(transaction), // RPC params are always expected to be a list)println("✅ Transaction hash: ${response.result}")