Introduction¶
The Arbitrum Python SDK is a powerful TypeScript library that streamlines interactions with Arbitrum networks. It offers robust tools for bridging tokens and passing messages between networks through an intuitive interface to the underlying smart contracts.
Key Features
Token Bridging: Effortlessly bridge tokens between Ethereum and Arbitrum.
Message Passing: Seamlessly pass messages across networks.
Contracts Interface: Leverage a strongly-typed interface for interacting with smart contracts.
Below is an overview of the Arbitrum Python SDK functionality. See the tutorials for more examples.
Install¶
pip3 install arbitrum_py
Using the Arbitrum Python SDK¶
Bridging assets¶
Arbitrum Python SDK can be used to bridge assets to or from an Arbitrum Network. The following asset bridgers are currently available:
All asset bridgers have the following methods which accept different parameters depending on the asset bridger type:
deposit - moves assets from the Parent to the Child chain
withdraw - moves assets from the Child to the Parent chain
Example ETH Deposit to Arbitrum One¶
from web3 import Web3
from arbitrum_py.data_entities.networks import get_arbitrum_network
from arbitrum_py.asset_bridger.eth_bridger import EthBridger
# get the ArbitrumNetwork object using the chain id of the Arbitrum One chain
child_network = get_arbitrum_network(42161)
eth_bridger = EthBridger(child_network)
eth_deposit_receipt = eth_bridger.deposit({
'amount': Web3.to_wei(23, 'ether'),
'parentSigner': parent_signer, # a SignerOrProvider instance connected to mainnet ethereum
'childProvider': child_provider, # a Web3 provider connected to Arbitrum One
})
print(f"Deposit initiated: {eth_deposit_receipt['transactionHash'].hex()}")
Example ETH Withdrawal from Arbitrum One¶
from web3 import Web3
from arbitrum_py.data_entities.networks import get_arbitrum_network
from arbitrum_py.asset_bridger.eth_bridger import EthBridger
# get the ArbitrumNetwork object using the chain id of the Arbitrum One chain
child_network = get_arbitrum_network(42161)
eth_bridger = EthBridger(child_network)
withdraw_receipt = eth_bridger.withdraw({
'amount': Web3.to_wei(23, 'ether'),
'childSigner': child_signer, # a SignerOrProvider instance connected to Arbitrum One
'destinationAddress': child_signer.account.address,
})
print(f"Withdrawal initiated: {withdraw_receipt['transactionHash'].hex()}")
Networks¶
Arbitrum Python SDK comes pre-configured for Mainnet and Sepolia, and their Arbitrum counterparts. Any other networks that are not pre-configured must be registered before being used.
Configuring Network¶
To interact with a custom ArbitrumNetwork, you can register it using the register_custom_arbitrum_network function.
from arbitrum_py.data_entities.networks import register_custom_arbitrum_network
register_custom_arbitrum_network({
'chainId': 123456,
'name': 'Custom Arbitrum Network',
})
Cross chain messages¶
When assets are moved by the Parent and Child cross chain messages are sent. The lifecycles of these messages are encapsulated in the classes ParentToChildMessage and ChildToParentMessage. These objects are commonly created from the receipts of transactions that send cross chain messages. A cross chain message will eventually result in a transaction being executed on the destination chain, and these message classes provide the ability to wait for that finalizing transaction to occur.
Redeem a Parent-to-Child Message¶
from arbitrum_py.message.parent_transaction import ParentTransactionReceipt
from arbitrum_py.message.parent_to_child_message import ParentToChildMessageStatus
# Create parent transaction receipt from a transaction receipt that triggered
# a Parent-to-Child message (e.g., depositing a token via a bridge)
parent_txn_receipt = ParentTransactionReceipt(txn_receipt)
# Get parent to child messages
messages = parent_txn_receipt.get_parent_to_child_messages(
child_signer # SignerOrProvider instance
)
parent_to_child_message = messages[0]
# Wait for status
result = parent_to_child_message.wait_for_status()
status = result['status']
if status == ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHILD:
# Message wasn't auto-redeemed; redeem it now:
response = parent_to_child_message.redeem()
receipt = response.wait_for_redeem()
elif status == ParentToChildMessageStatus.REDEEMED:
# Message successfully redeemed
pass
Inbox Tools¶
As part of normal operation, the Arbitrum sequencer will send messages into the rollup chain. However, if the sequencer is unavailable and not posting batches, the inbox tools can be used to force the inclusion of transactions into the Arbitrum network.
Here’s how you can use the inbox tools to withdraw ether from Arbitrum One without waiting for the sequencer:
from arbitrum_py.data_entities.networks import get_arbitrum_network
from arbitrum_py.inbox.inbox import InboxTools
from arbitrum_py.data_entities.constants import ARB_SYS_ADDRESS
from arbitrum_py.utils.helper import load_contract
# type(parent_signer) == SignerOrProvider
# type(child_provider) == Web3
# Get network and create InboxTools instance
child_network = get_arbitrum_network(child_provider.eth.chain_id)
inbox_sdk = InboxTools(parent_signer, child_network)
# Create ArbSys contract instance and encode withdraw function call
arb_sys = load_contract(
provider=child_provider,
contract_name="ArbSys",
address=ARB_SYS_ADDRESS
)
child_calldata = arb_sys.encodeABI(
fn_name='withdrawEth',
args=[parent_signer.account.address]
)
# Prepare transaction request
tx_child_request = {
'data': child_calldata,
'to': ARB_SYS_ADDRESS,
'value': 1,
}
# Sign and send transaction
child_signed_tx = inbox_sdk.sign_child_tx(
tx_child_request,
child_signer
)
child_tx_hash = parse_raw_tx(child_signed_tx)['hash']
results_parent = inbox_sdk.send_child_signed_tx(child_signed_tx)
inbox_receipt = parent_provider.eth.wait_for_transaction_receipt(
results_parent.transactionHash
)
Utils¶
EventFetcher - A utility to provide typing for the fetching of events
MultiCaller - A utility for executing multiple calls as part of a single RPC request. This can be useful for reducing round trips.
constants - A list of useful Arbitrum related constants
Development¶
Run Integration tests¶
Set up test nodes by following the instructions here or below quick setup:
# Make sure docker is installed
git clone -b release --recurse-submodules https://github.com/OffchainLabs/nitro-testnode.git && cd nitro-testnode
chmod +x ./test-node.bash && && ./test-node.bash --init --tokenbridge --l3node --l3-token-bridge --blockscout --detach
# (Optional) You can fund default accounts with ETH using the following command
# https://docs.arbitrum.io/run-arbitrum-node/run-local-full-chain-simulation#blockscout
# Send 5 ETH to the dev account in L2 network.
./test-node.bash script send-l2 --to 0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E --ethamount 5
# Send 5 ETH to the dev account in 12 network.
./test-node.bash script send-l1 --to 0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E --ethamount 5
Copy
.env.exampleto.envand update relevant environment variables.Install dependencies:
pip install -r requirements.txt
Generate the network configuration against your active Nitro test node:
python3 -m scripts.gen_network
Execute the integration tests:
pytest tests