Permissioned Keys
Permissioned Keys provide a way for different traders to share the same account. Using this mechanism, the owner of an account can provide different types of permissions, allowing flexibility to what and what not the permissioned users can do with its account.
A permission, or set of permissions, is also known as an authenticator. See all available authenticator types here.
This section will guide you through authenticators use and management. We show the two sides of this authenticating interaction. We'll label the main user, which gives the permissiones, as the owner, and the permissioned user as the trader.
Owner
Create an authenticator
Lets create an authenticator which allows only the trader to place orders.
To create this authenticator, we use two sub-authenticators: signatureVerification
and messageFilter
:
- the
signatureVerification
authenticator must be present in all authenticator sets and contains the trader's public key; - the
messageFilter
authenticator must contain the gRPC message ID of the allowed transaction (hereMsgPlaceOrder
).
We compose everything together using the composable authenticator AllOf
, stating that some trader's transaction is only allowed if it complies with all the authenticators.
The trader also needs to send the owner the its public key, associated with its address. This can be done by encoding the public key (e.g., hex string) and sending it. The owner then decodes it, serving it as input below.
# trader_key = trader_wallet.public_key.key
auth = Authenticator.compose(
# All sub-authenticators must be valid.
AuthenticatorType.AllOf,
[
# The allowed account.
Authenticator.signature_verification(trader_key),
# The allowed action.
Authenticator.message_filter("/dydxprotocol.clob.MsgPlaceOrder"),
],
)
Add the authenticator
Now we need to push the authenticator to the network.
# Add the authenticator.
response = await node.add_authenticator(wallet, auth)
List authenticators
You can confirm if the authenticator was added by listing all the authenticators associated with your (owner) address.
The added authenticator, identified by an ID (integer), will appear last on the list. The trader will then need to use this ID.
# List authenticators.
authenticators = await node.get_authenticators(wallet.address)
# Grab the last authenticator ID.
id = authenticators.account_authenticators[-1]
Remove the authenticator
Authenticators can be removed if they are needed anymore, or if the trader goes rogue.
# Remove the authenticator.
response = await node.remove_authenticator(wallet, id)
Trader
Get the authenticator ID
Grab the authenticator ID created by the owner in Owner::Step 2, either by:
- request to the owner through other channels, or;
- by using the list authenticators method to fetch the last authenticator (see Owner::Step 3).
Using the authenticator
Having the authenticator ID, the trader can now use it to perform the allowed actions.
In this example, the trader can use the authenticator to issue orders on the behalf of the owner.
id = ... # authenticator ID
# Create the order ID, using the owner address
order_id = market.order_id(
OWNER_ADDRESS, # address
0, # subaccount number
random.randint(0, 100000000), # client ID, can be random
OrderFlags.SHORT_TERM # short-term order
)
# Create the order as usual
order = market.order(
order_id,
# ...
)
# The TxOptions should have the authenticator ID to be used.
tx_options = TxOptions([id], wallet.sequence, wallet.account_number)
# Place the order.
place = await node.place_order(wallet, order, tx_options)