Skip to content

Commit

Permalink
Sign typed data using BrowserSigner
Browse files Browse the repository at this point in the history
Closes #128
  • Loading branch information
DanielSchiavini committed Feb 5, 2024
1 parent 1528a3e commit 3b26729
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 10 deletions.
18 changes: 18 additions & 0 deletions boa/integrations/jupyter/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ def send_transaction(self, tx_data: dict) -> dict:
)
return convert_frontend_dict(sign_data)

def sign_typed_data(
self, domain: dict[str, Any], types: dict[str, list], value: dict[str, Any]
) -> str:
"""
Sign typed data value with types data structure for domain using the EIP-712 specification.
:param domain: The domain data structure.
:param types: The types data structure.
:param value: The value to sign.
:return: The signature.
"""
return _javascript_call(
"signTypedData",
domain,
types,
value,
timeout_message=TRANSACTION_TIMEOUT_MESSAGE,
)


class BrowserRPC(RPC):
"""
Expand Down
16 changes: 8 additions & 8 deletions boa/integrations/jupyter/jupyter.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,16 @@
return response.text();
}

const getSigner = () => getEthersProvider().getSigner();

/** Load the signer via ethers user */
const loadSigner = async () => {
const signer = await getEthersProvider().getSigner();
return signer.getAddress();
};
const loadSigner = () => getSigner().then(s => s.getAddress());

/** Sign a transaction via ethers */
async function signTransaction(transaction) {
const signer = await getEthersProvider().getSigner();
return signer.sendTransaction(transaction);
}
const signTransaction = transaction => getSigner().then(s => s.signTransaction(transaction));

/** Sign a typed data via ethers */
const signTypedData = (domain, types, value) => getSigner().then(s => s.signTypedData(domain, types, value));

/** Call an RPC method via ethers */
const rpc = (method, params) => getEthersProvider().send(method, params);
Expand Down Expand Up @@ -91,6 +90,7 @@
window._titanoboa = {
loadSigner: handleCallback(loadSigner),
signTransaction: handleCallback(signTransaction),
signTypedData: handleCallback(signTypedData),
waitForTransactionReceipt: handleCallback(waitForTransactionReceipt),
rpc: handleCallback(rpc),
multiRpc: handleCallback(multiRpc),
Expand Down
14 changes: 12 additions & 2 deletions tests/unitary/jupyter/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from unittest.mock import MagicMock, patch

import pytest
from eth_account import Account

import boa

Expand Down Expand Up @@ -124,14 +123,15 @@ def mock_fork(mock_callback):

@pytest.fixture()
def browser(nest_asyncio_mock, jupyter_module_mock):
# Import the browser module after the mocks have been set up
from boa.integrations.jupyter import browser

return browser


@pytest.fixture()
def account():
return Account.create()
return boa.env.generate_address()


@pytest.fixture()
Expand All @@ -152,6 +152,16 @@ def test_browser_signer_given_address(browser, display_mock, mock_inject_javascr
mock_inject_javascript.assert_not_called()


def test_browser_sign_typed_data(
browser, display_mock, mock_inject_javascript, mock_callback
):
signer = browser.BrowserSigner(boa.env.generate_address())
signature = boa.env.generate_address()
mock_callback("signTypedData", signature)
data = signer.sign_typed_data({"name": "My App"}, {"types": []}, {"data": "0x1234"})
assert data == signature


def test_browser_signer_no_address(
mocked_token, browser, display_mock, mock_callback, mock_inject_javascript
):
Expand Down

0 comments on commit 3b26729

Please sign in to comment.