Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.PHONY: $(MAKECMDGOALS)
MAKEFLAGS += --no-print-directory
##
## 🚧 DipDup developer tools
##
PACKAGE=substrateinterface
TAG=latest
SOURCE=substrateinterface test examples


help: ## Show this help (default)
@grep -Fh "##" $(MAKEFILE_LIST) | grep -Fv grep -F | sed -e 's/\\$$//' | sed -e 's/##//'

##
##-- Dependencies
##

install: ## Install dependencies
uv sync

update: ## Update dependencies
uv lock

##
##-- CI
##

all: ## Run an entire CI pipeline
make format lint test

format: ## Format with all tools
make black

lint: ## Lint with all tools
make ruff mypy

test: ## Run tests
COVERAGE_CORE=sysmon pytest test

##

black: ## Format with black
black ${SOURCE}

ruff: ## Lint with ruff
ruff check --fix --unsafe-fixes ${SOURCE}

mypy: ## Lint with mypy
mypy ${SOURCE}
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ older or runtimes under development the `ss58_format` (default 42) and other pro

### Balance information of an account
```python
result = substrate.query('System', 'Account', ['F4xQKRUagnSGjFqafyhajLs94e7Vvzvr8ebwYJceKpr8R7T'])
result = await substrate.query('System', 'Account', ['F4xQKRUagnSGjFqafyhajLs94e7Vvzvr8ebwYJceKpr8R7T'])
print(result.value['data']['free']) # 635278638077956496
```
### Create balance transfer extrinsic

```python
call = substrate.compose_call(
call = await substrate.compose_call(
call_module='Balances',
call_function='transfer',
call_params={
Expand All @@ -51,9 +51,9 @@ call = substrate.compose_call(
)

keypair = Keypair.create_from_uri('//Alice')
extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair)
extrinsic = await substrate.create_signed_extrinsic(call=call, keypair=keypair)

receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
receipt = await substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

print(f"Extrinsic '{receipt.extrinsic_hash}' sent and included in block '{receipt.block_hash}'")
```
Expand Down
48 changes: 24 additions & 24 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ substrate = SubstrateInterface(

keypair = Keypair.create_from_uri('//Alice')

balance_call = substrate.compose_call(
balance_call = await substrate.compose_call(
call_module='Balances',
call_function='transfer_keep_alive',
call_params={
Expand All @@ -19,23 +19,23 @@ balance_call = substrate.compose_call(
}
)

call = substrate.compose_call(
call = await substrate.compose_call(
call_module='Utility',
call_function='batch',
call_params={
'calls': [balance_call, balance_call]
}
)

extrinsic = substrate.create_signed_extrinsic(
extrinsic = await substrate.create_signed_extrinsic(
call=call,
keypair=keypair,
era={'period': 64}
)


try:
receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
receipt = await substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

print('Extrinsic "{}" included in block "{}"'.format(
receipt.extrinsic_hash, receipt.block_hash
Expand All @@ -44,7 +44,7 @@ try:
if receipt.is_success:

print('✅ Success, triggered events:')
for event in receipt.triggered_events:
for event in (await receipt.triggered_events()):
print(f'* {event.value}')

else:
Expand All @@ -71,7 +71,7 @@ substrate = SubstrateInterface(

keypair = Keypair.create_from_uri('//Alice')

call = substrate.compose_call(
call = await substrate.compose_call(
call_module='Balances',
call_function='transfer_keep_alive',
call_params={
Expand All @@ -95,7 +95,7 @@ substrate = SubstrateInterface(
url="ws://127.0.0.1:9944"
)

result = substrate.query_map("System", "Account", max_results=100)
result = await substrate.query_map("System", "Account", max_results=100)

for account, account_info in result:
print(f'* {account.value}: {account_info.value}')
Expand All @@ -122,7 +122,7 @@ multisig_account = substrate.generate_multisig_account(
threshold=2
)

call = substrate.compose_call(
call = await substrate.compose_call(
call_module='Balances',
call_function='transfer_keep_alive',
call_params={
Expand All @@ -132,18 +132,18 @@ call = substrate.compose_call(
)

# Initiate multisig tx
extrinsic = substrate.create_multisig_extrinsic(call, keypair_alice, multisig_account, era={'period': 64})
extrinsic = await substrate.create_multisig_extrinsic(call, keypair_alice, multisig_account, era={'period': 64})

receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
receipt = await substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

if not receipt.is_success:
print(f"⚠️ {receipt.error_message}")
exit()

# Finalize multisig tx with other signatory
extrinsic = substrate.create_multisig_extrinsic(call, keypair_bob, multisig_account, era={'period': 64})
extrinsic = await substrate.create_multisig_extrinsic(call, keypair_bob, multisig_account, era={'period': 64})

receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
receipt = await substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

if receipt.is_success:
print(f"✅ {receipt.triggered_events}")
Expand All @@ -167,22 +167,22 @@ keypair = Keypair.create_from_uri('//Alice')
contract_address = "5GhwarrVMH8kjb8XyW6zCfURHbHy3v84afzLbADyYYX6H2Kk"

# Check if contract is on chain
contract_info = substrate.query("Contracts", "ContractInfoOf", [contract_address])
contract_info = await substrate.query("Contracts", "ContractInfoOf", [contract_address])

if contract_info.value:

print(f'Found contract on chain: {contract_info.value}')

# Create contract instance from deterministic address
contract = ContractInstance.create_from_address(
contract = await ContractInstance.create_from_address(
contract_address=contract_address,
metadata_file=os.path.join(os.path.dirname(__file__), 'assets', 'flipper.json'),
substrate=substrate
)
else:

# Upload WASM code
code = ContractCode.create_from_contract_files(
code = await ContractCode.create_from_contract_files(
metadata_file=os.path.join(os.path.dirname(__file__), 'assets', 'flipper.json'),
wasm_file=os.path.join(os.path.dirname(__file__), 'assets', 'flipper.wasm'),
substrate=substrate
Expand Down Expand Up @@ -236,9 +236,9 @@ from substrateinterface import SubstrateInterface
substrate = SubstrateInterface(url="ws://127.0.0.1:9944")

block_number = 10
block_hash = substrate.get_block_hash(block_number)
block_hash = await substrate.get_block_hash(block_number)

result = substrate.query(
result = await substrate.query(
"System", "Account", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"], block_hash=block_hash
)

Expand All @@ -261,10 +261,10 @@ from substrateinterface import SubstrateInterface
substrate = SubstrateInterface(url="ws://127.0.0.1:9944")


def subscription_handler(obj, update_nr, subscription_id):
async def subscription_handler(obj, update_nr, subscription_id):
print(f"New block #{obj['header']['number']}")

block = substrate.get_block(block_number=obj['header']['number'])
block = await substrate.get_block(block_number=obj['header']['number'])

for idx, extrinsic in enumerate(block['extrinsics']):
print(f'# {idx}: {extrinsic.value}')
Expand All @@ -287,7 +287,7 @@ substrate = SubstrateInterface(
)


def subscription_handler(account_info_obj, update_nr, subscription_id):
async def subscription_handler(account_info_obj, update_nr, subscription_id):

if update_nr == 0:
print('Initial account data:', account_info_obj.value)
Expand All @@ -301,7 +301,7 @@ def subscription_handler(account_info_obj, update_nr, subscription_id):
return account_info_obj


result = substrate.query("System", "Account", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"],
result = await substrate.query("System", "Account", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"],
subscription_handler=subscription_handler)

print(result)
Expand All @@ -313,18 +313,18 @@ print(result)
from substrateinterface import SubstrateInterface


def subscription_handler(storage_key, updated_obj, update_nr, subscription_id):
async def subscription_handler(storage_key, updated_obj, update_nr, subscription_id):
print(f"Update for {storage_key.params[0]}: {updated_obj.value}")


substrate = SubstrateInterface(url="ws://127.0.0.1:9944")

# Accounts to track
storage_keys = [
substrate.create_storage_key(
await substrate.create_storage_key(
"System", "Account", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"]
),
substrate.create_storage_key(
await substrate.create_storage_key(
"System", "Account", ["5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"]
)
]
Expand Down
8 changes: 4 additions & 4 deletions docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ older or runtimes under development the `ss58_format` (default 42) and other pro

### Balance information of an account
```python
result = substrate.query('System', 'Account', ['F4xQKRUagnSGjFqafyhajLs94e7Vvzvr8ebwYJceKpr8R7T'])
result = await substrate.query('System', 'Account', ['F4xQKRUagnSGjFqafyhajLs94e7Vvzvr8ebwYJceKpr8R7T'])
print(result.value['data']['free']) # 635278638077956496
```
### Create balance transfer extrinsic

```python
call = substrate.compose_call(
call = await substrate.compose_call(
call_module='Balances',
call_function='transfer_keep_alive',
call_params={
Expand All @@ -32,8 +32,8 @@ call = substrate.compose_call(
}
)
keypair = Keypair.create_from_uri('//Alice')
extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair)
receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
extrinsic = await substrate.create_signed_extrinsic(call=call, keypair=keypair)
receipt = await substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

print(f"Extrinsic '{receipt.extrinsic_hash}' sent and included in block '{receipt.block_hash}'")
```
6 changes: 3 additions & 3 deletions docs/usage/call-runtime-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ A Runtime API facilitates this kind of communication between the outer node and

## Example
```python
result = substrate.runtime_call("AccountNonceApi", "account_nonce", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"])
result = await substrate.runtime_call("AccountNonceApi", "account_nonce", ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"])
# <U32(value=2)>
```

## List of available runtime APIs and methods

```python
runtime_calls = substrate.get_metadata_runtime_call_functions()
runtime_calls = await substrate.get_metadata_runtime_call_functions()
#[
# <RuntimeCallDefinition(value={'description': 'The API to query account nonce (aka transaction index)', 'params': [{'name': 'account_id', 'type': 'AccountId'}], 'type': 'Index', 'api': 'AccountNonceApi', 'method': 'account_nonce'})>
# ...
Expand All @@ -26,7 +26,7 @@ runtime_calls = substrate.get_metadata_runtime_call_functions()
A helper function to compose the parameters for this runtime API call

```python
runtime_call = substrate.get_metadata_runtime_call_function("ContractsApi", "call")
runtime_call = await substrate.get_metadata_runtime_call_function("ContractsApi", "call")
param_info = runtime_call.get_param_info()
# ['AccountId', 'AccountId', 'u128', 'u64', (None, 'u128'), 'Bytes']
```
2 changes: 1 addition & 1 deletion docs/usage/cleanup-and-context-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ When using the context manager this will be done automatically:

```python
with SubstrateInterface(url="wss://rpc.polkadot.io") as substrate:
events = substrate.query("System", "Events")
events = await substrate.query("System", "Events")

# connection is now closed
```
Loading