Policies API
API endpoints to create, list, update, archive, and manage policies that enforce business rules and approval workflows on wallet activity.
- an Activity kind: the type of activity that this policy should gate.
- a Rule: defines the rule being evaluated to know whether the policy should “activate” (aka “trigger”) or not for a given activity happening in the system.
- an Action: after rule was evaluated, if the policy is triggered, the action defines what action is taken as a consequence.
- optional Filters: these can be used to reduce the scope upon which the policy applies.
Skipped if the rule did not apply or is triggered executing the associated action. If the action is RequestApproval, an Approval process is initiated.
Wallets:Sign policies, this means before the MPC signing ceremony begins. For other activity kinds (permission changes, policy modifications, address alias updates, etc.), the action is held until the policy resolves. A blocked or unapproved request never takes effect.AlwaysTrigger rule and Block action, then create separate policies for allowed cases.Activities
“Activity” is a generic term describing some activity in the DFNS system. Supported activity kinds are:Wallets:Sign, Wallets:IncomingTransaction, Permissions:Assign, Permissions:Modify, Policies:Modify, Registry:Addresses:Modify, Registry:ContractSchemas:Modify.
Wallets:Sign activity
A “Wallets:Sign” activity represents any activity which involves signing with a wallet. Currently, in our API, these can be:
- a Transfer Request (created using the endpoint Transfer Asset from Wallet)
- a Transaction Request (created using the endpoint Broadcast Transaction from Wallet)
- a Signature Request (created using the endpoint Generate Signature from Keys)
Wallets:IncomingTransaction activity
A “Wallets:IncomingTransaction” activity represents when our indexers detected an incoming transaction into a wallet. This activity kind has to be used with the rule kind “ChainalysisTransactionScreening” (see more on Chainalysis integration page), and the action kind “NoAction”, meaning that no actual action will be taken as a result of the Chainalysis screening, other than notifying you through a webhook event if the policy is triggered. The reason for that, is that the incoming transaction is already on-chain, so the funds are already in the wallet, we cannot block that transfer on chain.
Permissions:Modify activity
A “Permissions:Modify” activity represents any activity which involves updating or archiving a permission. These activities are Permission change requests, created as a result of calling either:
- the endpoint Update Permission
- the endpoint Archive Permission
Permissions:Assign activity
A “Permissions:Assign” activity represents any activity which involves assigning a permission (or revoking it, aka “deleting a permission assignment”). These activities are Assignment change requests, created as a result of calling either:
- the endpoint Assign Permission
- the endpoint Revoke Permission
Policies:Modify activity
A “Policies:Modify” activity represents any activity which involves updating or archiving a policy. These activities are Policy change requests, created as a result of calling either:
- the endpoint Update Policy
- the endpoint Delete Policy
Registry:Addresses:Modify activity
A “Registry:Addresses:Modify” activity represents any activity which updates or deletes an address alias in the Address Book. Address aliases are managed from the dashboard. This activity kind only supports the AlwaysTrigger rule and no filters.
Registry:ContractSchemas:Modify activity
A “Registry:ContractSchemas:Modify” activity represents any activity which modifies a smart contract schema (ABI) registered in the dashboard. This includes updating or deleting an imported contract. See Interacting with smart contracts for how contract schemas are managed. This activity kind only supports the AlwaysTrigger rule and no filters.
Every policy requires a rule to be specified. Upon policy evaluation, the configuration specified in the rule will be used to determine whether the policy should trigger or not for a given activity.
By exposing controls on permissions and policies, DFNS enables the specification of an admin quorum to approve sensitive actions which could change system governance. Note DFNS does not expose a separate “admin quorum” concept like some of our competitors - we simply enable this use case as another configuration of the policy engine itself. This was chosen to promote flexibility as not every customer will have the same requirements around creating and managing admin quorums.
Policy Rules
The policy rule is what gets evaluated to determine whether a given activity will “activate” (aka “trigger”) the policy, therefore applying the policy “Action”, or whether it will skip it. Supported Policy Rule kinds are:AlwaysTrigger, TransactionAmountLimit, TransactionAmountVelocity, TransactionCountVelocity, TransactionRecipientWhitelist, ChainalysisTransactionPrescreening, ChainalysisTransactionScreening, GlobalLedgerTransactionPrescreening, TravelRuleTransactionPrescreening.
AlwaysTrigger policy rule
This rule can be used on a policy of any activityKind. It will always be triggered, meaning that if this rule is defined on a policy, the policy will always trigger the policy action, regardless of the activity details.
TransactionAmountLimit policy rule
This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the wallet activity detected is transferring some value which amount is greater than a given limit.
TransactionAmountVelocity policy rule
This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the cumulative amount transferred from a given wallet within a given timeframe is greater than a specified limit. The aggregate amount evaluated is based only on the wallet that triggered the policy.
TransactionCountVelocity policy rule
This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the number of wallet activities for a given wallet within a given timeframe, is greater than a specified limit. The aggregate number of transactions evaluated is based only on the wallet that triggered the policy.
TransactionRecipientWhitelist policy rule
This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the wallet activity transfers some value to a recipient and the destination address is NOT whitelisted.
ChainalysisTransactionPrescreening policy rule
activityKind = Wallets:Sign. It’s a rule based on Chainalysis KYT integration (Know-Your-Transaction). Upon transfer attempt, we will first register the transfer with Chainalysis (as a “withdrawal attempt”), and fetch the screening results (alerts, exposures, addresses detected). Based on the results, and the configuration of this rule, the policy will be triggered.
It’s called “Pre”-screening, because the scanned transaction is not on chain yet, it’s still a transaction attempt (before the transaction actually make it on chain).
ChainalysisTransactionScreening policy rule
activityKind = Wallets:IncomingTransaction, and with the action kind NoAction. It’s a rule based on Chainalysis KYT integration (Know-Your-Transaction). Upon an incoming transaction detected by our indexers, we will register the transfer with Chainalysis, and fetch the results of the analysis (alerts & exposures detected). Based on the results, and the configuration of this rule, the policy will be triggered.
The shape of the rule is almost like the ChainalysisTransactionPrescreening rule, except the address property is not supported.
ChainalysisTransactionPrescreening
GlobalLedgerTransactionPrescreening policy rule
activityKind = Wallets:Sign. It’s a rule based on Global Ledger KYT integration (Know-Your-Transaction). Upon transfer attempt, we will send the transaction to Global Ledger for screening and fetch the risk score and any alerts. Based on the results, and the configuration of this rule, the policy will be triggered.
The policy triggers when either:
- The transaction’s risk score meets or exceeds your configured
riskScoreThreshold - Global Ledger returns any alerts for the transaction
TravelRuleTransactionPrescreening policy rule
activityKind = Wallets:Sign,and with the action kind Block. It’s a rule based on Notabene TravelRule integration. It ONLY applies to DFNS Transfer Asset Api Calls. It is NOT supported for Transfers initiated via the dashboard. Upon transfer attempt with an optional TravelRule payload, we will call Notabene’s APIs on your behalf to both confirm the validity of the travel rule message and submit it for processing. DFNS then waits for a response from the counterparty (for custodial transfers) or Notabene (for non-custodial transfers).
It’s called “Pre”-screening, because the transaction is not on chain yet, it’s still a transaction attempt (before the transaction actually make it on chain).
Policy Action
An action specifies what should happen if a policy rule is triggered. Supported action kinds are:BlockandRequestApproval.
Block policy action
This action means that the activity will be blocked if the policy is triggered.
RequestApproval policy action
This action means that activity will first require an Approval process to be completed before it can be executed (or be aborted if someone rejects it during the approval process).
One or several groups of approvers need to be specified. These groups define who is allowed to approve / reject an activity.
The activity will only be executed if all approver groups reach their “quorum” of approvals. Otherwise, if any one user within any approver group rejects, then the activity is aborted and the call is not executed.
The example below shows a RequestApproval action, configured with one approval group requiring 2 approvals amongst three specific users.
NoAction policy action
This action kind means that nothing will happen after policy rule evaluation. It’s meant to be used with KYT policy rules like ChainalysisTransactionPrescreening, ChainalysisTransactionScreening, or GlobalLedgerTransactionPrescreening. This action is for when you just want the KYT analysis rule to be run, and then if triggered, those results returned in a policy.triggered Webhook Event.
Policy Filters
Policy filters can reduce the scope on which the policy applies. If no filters are specified, the policy applies to all activities happening in your organisation (all activities of the kind defined by the policyactivityKind).
For example, you can use filters to setup a policy for activities happening on specific wallets or on groups of wallets. Some examples include:
- “All activities from wallets tagged ‘
group:treasury’ must first be approved by the CEO - “All transfers from wallet ID 1 larger than $1k must first be approved by the CEO & the CFO”
- “All transfers from wallets tagged ‘
accounting:freeze’ must be blocked”
activityKind of your policy (activityKind)
Filters for "Wallets:Sign" activity
- The policy is scoped only to wallets with IDs
wa-1orwa-2:
- The policy is scoped only to wallets tagged either “
domain:accounting” or “sensitive”:
- The policy is scoped only to wallets tagged with both “
domain:accounting” and “sensitive”:
- The policy is scoped only to wallets containing all these tags (“
domain:accounting”, “zone:asia”) AND at least one of these tags (“security:high”, “security:medium”):
Filters for "Policies:Modify" activity
| filter key | evaluator | Value |
|---|---|---|
policyId | in | List of policy IDs. If the policy being modified is one of these IDs, the policy applies. |
- The policy is scoped only to policies with IDs
plc-1orplc-2
Filters for "Permissions:Modify" activity
- The policy is scoped only to permissions with IDs
pm-1orpm-2
Filters for "Permissions:Assign" activity
- The policy is scoped only to permissions with IDs
pm-1orpm-2
Policy object
- Registry:Addresses:Modify
- Permissions:Assign
- Permissions:Modify
- Policies:Modify
- Registry:ContractSchemas:Modify
- Wallets:Sign
- Wallets:IncomingTransaction
Active, Archived Registry:Addresses:Modify This rule will always be triggered, meaning that if this rule is defined on a policy, the policy will always trigger the policy action, regardless of the activity details.
This action means that activity will first require an Approval process to be completed before it can be executed (or be aborted if someone rejects it during the approval process).
One or several groups of approvers need to be specified. These groups define who is allowed to approve / reject an activity.
The activity will only be executed if all approver groups reach their "quorum" of approvals. Otherwise, if any one user within any approver group rejects, then the activity is aborted and the call is not executed.
The example below shows a RequestApproval action, configured with one approval group requiring 2 approvals amongst three specific users.
Don't lock yourself up
By default, users cannot approve an activity they initiated themselves, even if they are in an approval group. To allow this, you must set initiatorCanApprove: true.
Example 1: For any wallet transfer, a policy is setup to require approval from 1 specific admin user (eg. the CEO). initiatorCanApprove was not set to true. If the CEO himself initiates a transfer, no-one can approve his transfer and it's stuck.
Example 2: Company has only 3 users. A policy is setup to require approval from any 3 users (quorum: 3) for any modification of a policy. initiatorCanApprove was not set to true. In this case, they are locked, and the policy cannot be modified: whoever requests a modification cannot approve, and the policy is therefore always missing one approver. To unlock, they would need to invite a new user and give him the rights to approve as well.
- RequestApproval
- Block