cdp-docs-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,730 @@
1
+ # Govern behavior using Policies
2
+
3
+ ## Overview
4
+
5
+ CDP Wallets support **Policies** that enable developers to govern account and project behavior. Policies provide flexible configuration for enforcing controls based on transaction parameters such as destination address and transaction value.
6
+
7
+ ### Use cases
8
+
9
+ * **Wallet transaction filtering:** Prevent transfers to known malicious or restricted addresses
10
+ * **Allowlisted access to project features:** Restrict access only to approved addresses to interact with a smart contract or mint a token
11
+ * **Transaction limits per address:** Limit financial risk by capping transaction values
12
+ * **Prevent signing of fraudulent messages:** Ensure compromised clients cannot prove control of your accounts
13
+
14
+ ### Policy field definitions
15
+
16
+ A policy is defined by the following fields:
17
+
18
+ | Field | Description | Valid values |
19
+ | ----------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
20
+ | `scope` | The level at which a policy gets applied | `project` or `account` |
21
+ | `rules` | A list of rules that are used to govern the behavior of accounts | An array of rules |
22
+ | `action` | The action to take when a policy is applied | `accept` or `reject` |
23
+ | `operation` | The operation to perform when a policy is applied | `signEvmTransaction`, `sendEvmTransaction`, `signEvmMessage`, `signEvmHash`, or `signSolTransaction` |
24
+ | `criteria` | The list of logical expressions that are evaluated to a transaction to determine whether a rule should be applied or not | An array of criteria. See [API Reference](/api-reference/v2/rest-api/policy-engine/policy-engine) for more details. |
25
+
26
+ ### Evaluation process
27
+
28
+ A `project`-level policy will be evaluated first, followed by any `account`-level policies. Read more technical details on policy evaluation in the [API Reference documentation](/api-reference/v2/rest-api/policy-engine/policy-engine).
29
+
30
+ ```json project-policy.json [expandable] lines wrap
31
+ {
32
+ "description": "An example project level policy",
33
+ "scope": "project",
34
+ "rules": [
35
+ {
36
+ "action": "accept",
37
+ "operation": "signEvmTransaction",
38
+ "criteria": [
39
+ {
40
+ "type": "ethValue",
41
+ "ethValue": "1000000000000000000",
42
+ "operator": "<="
43
+ }
44
+ ]
45
+ },
46
+ {
47
+ "action": "accept",
48
+ "operation": "signEvmTransaction",
49
+ "criteria": [
50
+ {
51
+ "type": "ethValue",
52
+ "ethValue": "2000000000000000000",
53
+ "operator": "<="
54
+ },
55
+ {
56
+ "type": "evmAddress",
57
+ "addresses": [
58
+ "0x123"
59
+ ],
60
+ "operator": "in"
61
+ }
62
+ ]
63
+ }
64
+ ]
65
+ }
66
+ ```
67
+
68
+ <Accordion title="How would this policy be evaluated?">
69
+ In this example, the policy has two rules. An incoming transaction would be processed against each rule as follows:
70
+
71
+ 1. Accept any transaction with a value less than or equal to 1 ETH (expressed in Wei).
72
+ 2. Accept any transaction with a value less than or equal to 2 ETH, and an address in the allowlist.
73
+
74
+ Assume we have two transaction requests to the same address, 0x123:
75
+
76
+ 1. Transaction A with a value of 0.5 ETH
77
+ 2. Transaction B with a value of 2 ETH
78
+
79
+ * **Transaction A** would be accepted on the first rule, and the policy engine would stop evaluation against this policy.
80
+ * **Transaction B** would be processed against both rules. It would be rejected on the first rule, but accepted once processed against the second rule.
81
+ </Accordion>
82
+
83
+ ### Supported operations
84
+
85
+ Each rule defines the behavior of a certain `operation`. The `operation` corresponds to a CDP v2 API. Currently, the following operations are supported:
86
+
87
+ * `signEvmTransaction`: To identify incoming signing transactions on an EVM compatible network
88
+ * `sendEvmTransaction`: To identify incoming signing transactions that are then sent to a supported network.
89
+ * `signEvmMessage`: To identify incoming messages to be signed by an account.
90
+ * `signEvmHash`: To identify incoming hash to be signed by an account.
91
+ * `signSolTransaction`: To identify incoming signing transactions on the Solana network
92
+
93
+ You can find more details in the [API reference documentation](/api-reference/v2/rest-api/policy-engine/policy-engine).
94
+
95
+ ### API Key Configuration
96
+
97
+ In order to securely manage Policies via API or SDK, you'll need to manually configure an API key with a specific scope.
98
+
99
+ This scope is required to perform the following API operations:
100
+
101
+ * Create Policy
102
+ * Update Policy
103
+ * Delete Policy
104
+ * Account Policy assignment
105
+
106
+ When you're creating a new API Key, first expand the **API restrictions** panel then scroll down to the **API-specific restrictions** section.
107
+
108
+ Ensure that **Manage (modify policies)** is checked before key creation as seen in the following screenshot.
109
+
110
+ <Frame>
111
+ ![Policies Scope](https://mintlify.s3.us-west-1.amazonaws.com/coinbase-prod/wallet-api/images/manage-policies-api-scope.png)
112
+ </Frame>
113
+
114
+ ## Define a policy
115
+
116
+ Policies can be defined via CDP Portal UI or via the CDP SDK.
117
+
118
+ <Note>
119
+ You may only create one project-level policy per project.
120
+ </Note>
121
+
122
+ ### UI (CDP Portal)
123
+
124
+ 1. Navigate to [Policies](https://portal.cdp.coinbase.com/products/wallet-api/policy-engine) in the CDP Portal.
125
+ <Frame>
126
+ ![Policies UI](https://mintlify.s3.us-west-1.amazonaws.com/coinbase-prod/wallet-api/images/policy-engine-dashboard.png)
127
+ </Frame>
128
+
129
+ 2. Click the **Create new policy** button to access the JSON editor. The modal will contain a sample policy that you can edit, but you can also use some of the [examples](#example-policies) below.
130
+
131
+ <Frame>
132
+ ![JSON Editor](https://mintlify.s3.us-west-1.amazonaws.com/coinbase-prod/wallet-api/images/policy-engine-editor-modal.png)
133
+ </Frame>
134
+
135
+ 3. Define the policy and click the **Create** button. If successful, you should see a "Policy created" message.
136
+
137
+ 4. Refresh the page to see the new policy listed in the Policies dashboard:
138
+
139
+ <Frame>
140
+ ![Policy Engine dashboard](https://mintlify.s3.us-west-1.amazonaws.com/coinbase-prod/wallet-api/images/policy-engine-policies-dashboard.png)
141
+ </Frame>
142
+
143
+ Click the **View** button to edit or delete the policy.
144
+
145
+ 5. Account level policies should be added to the account programmatically via the SDK.
146
+
147
+ <CodeGroup>
148
+ ```ts TypeScript lines wrap
149
+ import { CdpClient } from "@coinbase/cdp-sdk";
150
+ import dotenv from "dotenv";
151
+
152
+ dotenv.config();
153
+
154
+ const cdp = new CdpClient();
155
+
156
+ const account = await cdp.evm.createAccount();
157
+
158
+ const policyId = "" // Paste the policy ID created on portal.
159
+
160
+ // Update the account to add the account policy.
161
+ const updatedAccount = await cdp.evm.updateAccount({
162
+ address: account.address,
163
+ update: {
164
+ accountPolicy: policyId,
165
+ }
166
+ })
167
+
168
+ console.log("Updated account %s with policy: %s", updatedAccount.address, updatedAccount.policies);
169
+ ```
170
+
171
+ ```python Python lines wrap
172
+ import asyncio
173
+
174
+ from cdp import CdpClient
175
+ from dotenv import load_dotenv
176
+ from cdp.update_account_types import UpdateAccountOptions
177
+
178
+ load_dotenv()
179
+
180
+ async def main():
181
+ async with CdpClient() as cdp:
182
+ account = await cdp.evm.create_account()
183
+
184
+ policy_id = "" # Paste the policy ID created on portal.
185
+
186
+ updatedAccount = await cdp.evm.update_account(
187
+ address=account.address,
188
+ update=UpdateAccountOptions(
189
+ account_policy=policy_id,
190
+ ),
191
+ )
192
+
193
+ print(f"Updated account {account.address} with policy {updatedAccount.policies}")
194
+
195
+ asyncio.run(main())
196
+ ```
197
+ </CodeGroup>
198
+
199
+ ### Programmatically
200
+
201
+ <Note>
202
+ In order to manage Policies via SDK or API, you need to have an API Key with [Policy management enabled](#api-key-configuration)
203
+ </Note>
204
+
205
+ To create a policy programmatically, you can use the CDP SDK. The code below will:
206
+
207
+ 1. Create an EVM account named `PolicyAccount`
208
+ 2. Create an account-level policy that only allows transactions less than or equal to 1 ETH to the address `0x000000000000000000000000000000000000dEaD`
209
+ 3. Apply the policy to the account we created
210
+ 4. Create another account named `OtherPolicyAccount` which has the above policy applied during creation
211
+ 5. Create a project-level policy that only allows transactions less than or equal to 5 ETH to the address `0x000000000000000000000000000000000000dEaD`
212
+
213
+ <Note>
214
+ A project-level policy is automatically applied to all accounts in the project on creation.
215
+
216
+ An account-level policy may be applied to an account in 2 ways: *during* account creation, or *after* account creation by updating the account.
217
+ </Note>
218
+
219
+ <CodeGroup>
220
+ ```ts TypeScript [expandable] lines wrap
221
+ import { CdpClient } from "@coinbase/cdp-sdk";
222
+
223
+ const cdp = new CdpClient();
224
+
225
+ const account = await cdp.evm.getOrCreateAccount({
226
+ name: "PolicyAccount"
227
+ });
228
+ console.log("Account address:", account.address);
229
+
230
+ // Create policy
231
+ const policy = await cdp.policies.createPolicy({
232
+ policy: {
233
+ scope: "account",
234
+ description: "Account Allowlist Example",
235
+ rules: [
236
+ {
237
+ action: "accept",
238
+ operation: "signEvmTransaction",
239
+ criteria: [
240
+ {
241
+ type: "ethValue",
242
+ ethValue: "1000000000000000000", // 1 ETH in wei
243
+ operator: "<=",
244
+ },
245
+ {
246
+ type: "evmAddress",
247
+ addresses: ["0x000000000000000000000000000000000000dEaD"],
248
+ operator: "in",
249
+ },
250
+ ],
251
+ },
252
+ ],
253
+ },
254
+ });
255
+ console.log("Created policy:", policy.id);
256
+
257
+ // Apply policy to the account
258
+ const updatedAccount = await cdp.evm.updateAccount({
259
+ address: account.address,
260
+ update: {
261
+ accountPolicy: policy.id
262
+ }
263
+ });
264
+ console.log("Applied policy to account:", updatedAccount.address);
265
+
266
+ // Create another account with policy immediately applied to it
267
+ const otherAccount = await cdp.evm.createAccount({
268
+ name: "OtherPolicyAccount",
269
+ accountPolicy: policy.id
270
+ });
271
+ console.log("Other account address:", otherAccount.address);
272
+
273
+ // Create project policy example
274
+ const projectPolicy = await cdp.policies.createPolicy({
275
+ policy: {
276
+ scope: "project",
277
+ description: "Project Transaction Limit Example",
278
+ rules: [
279
+ {
280
+ action: "accept",
281
+ operation: "signEvmTransaction",
282
+ criteria: [
283
+ {
284
+ type: "ethValue",
285
+ ethValue: "5000000000000000000", // 5 ETH in wei
286
+ operator: "<=",
287
+ },
288
+ {
289
+ type: "evmAddress",
290
+ addresses: ["0x000000000000000000000000000000000000dEaD"],
291
+ operator: "in",
292
+ },
293
+ ],
294
+ },
295
+ ],
296
+ },
297
+ });
298
+ console.log("Created project policy:", projectPolicy.id);
299
+ ```
300
+
301
+ ```python Python lines wrap [expandable]
302
+ import asyncio
303
+ from cdp import CdpClient
304
+ from dotenv import load_dotenv
305
+ from cdp.policies.types import CreatePolicyOptions, EthValueCriterion, EvmAddressCriterion, SignEvmTransactionRule
306
+ from cdp.update_account_types import UpdateAccountOptions
307
+
308
+ load_dotenv()
309
+
310
+ async def main():
311
+ cdp = CdpClient()
312
+
313
+ account = await cdp.evm.get_or_create_account(name="PolicyAccount")
314
+ print(f"Account address: {account.address}")
315
+
316
+ # Create policy
317
+ policy = await cdp.policies.create_policy(
318
+ policy=CreatePolicyOptions(
319
+ scope="account",
320
+ description="Account Allowlist Example",
321
+ rules=[
322
+ SignEvmTransactionRule(
323
+ action="accept",
324
+ criteria=[
325
+ EthValueCriterion(
326
+ ethValue="1000000000000000000", # 1 ETH in wei
327
+ operator="<=",
328
+ ),
329
+ EvmAddressCriterion(
330
+ addresses=["0x000000000000000000000000000000000000dEaD"],
331
+ operator="in",
332
+ ),
333
+ ],
334
+ )
335
+ ],
336
+ )
337
+ )
338
+ print(f"Created policy: {policy.id}")
339
+
340
+ # Apply policy to the account
341
+ updated_account = await cdp.evm.update_account(
342
+ address=account.address,
343
+ update=UpdateAccountOptions(
344
+ account_policy=policy.id
345
+ ),
346
+ )
347
+ print(f"Applied policy to account: {updated_account.address}")
348
+
349
+ # Create another account with policy immediately applied to it
350
+ other_account = await cdp.evm.create_account(
351
+ name="OtherPolicyAccount",
352
+ account_policy=policy.id,
353
+ )
354
+ print(f"Other account address: {other_account.address}");
355
+
356
+ # Create project policy example
357
+ project_policy = await cdp.policies.create_policy(
358
+ policy=CreatePolicyOptions(
359
+ scope="project",
360
+ description="Project Transaction Limit Example",
361
+ rules=[
362
+ SignEvmTransactionRule(
363
+ action="accept",
364
+ criteria=[
365
+ EthValueCriterion(
366
+ ethValue="5000000000000000000", # 5 ETH in wei
367
+ operator="<=",
368
+ ),
369
+ EvmAddressCriterion(
370
+ addresses=["0x000000000000000000000000000000000000dEaD"],
371
+ operator="in",
372
+ ),
373
+ ],
374
+ )
375
+ ],
376
+ )
377
+ )
378
+ print(f"Created project policy: {project_policy.id}")
379
+
380
+ await cdp.close()
381
+
382
+
383
+ asyncio.run(main())
384
+ ```
385
+ </CodeGroup>
386
+
387
+ Continue reading to learn more on how to allowlist, denylist, or limit transactions.
388
+
389
+ ## Example policies
390
+
391
+ ### Allowlist
392
+
393
+ The following example demonstrates a policy that allows signing transactions only to specific EVM addresses. Transactions to any address outside of this list will automatically be deleted by the policy engine.
394
+
395
+ ```json allow-list-policy.json lines wrap
396
+ {
397
+ "description": "Allowlist policy example",
398
+ "rules": [
399
+ {
400
+ "action": "accept",
401
+ "criteria": [
402
+ {
403
+ "addresses": [
404
+ "0xffffffffffffffffffffffffffffffffffffffff",
405
+ "0x1111111111111111111111111111111111111111"
406
+ ],
407
+ "operator": "in",
408
+ "type": "evmAddress"
409
+ }
410
+ ],
411
+ "operation": "signEvmTransaction"
412
+ }
413
+ ],
414
+ "scope": "project"
415
+ }
416
+ ```
417
+
418
+ The above policy treats the set of `addresses` as an allowlist, only accepting sign transaction requests to an EVM address that is `in` the set.
419
+
420
+ ### Denylist
421
+
422
+ The following example demonstrates a policy that rejects signing transactions to specific EVM addresses. Transactions with `to` field set to any address outside of this list will be accepted.
423
+
424
+ ```json deny-list-policy.json lines wrap
425
+ {
426
+ "description": "Denylist policy example",
427
+ "rules": [
428
+ {
429
+ "action": "accept",
430
+ "criteria": [
431
+ {
432
+ "addresses": [
433
+ "0xffffffffffffffffffffffffffffffffffffffff",
434
+ "0x1111111111111111111111111111111111111111"
435
+ ],
436
+ "operator": "not in",
437
+ "type": "evmAddress"
438
+ }
439
+ ],
440
+ "operation": "signEvmTransaction"
441
+ }
442
+ ],
443
+ "scope": "project"
444
+ }
445
+ ```
446
+
447
+ The above policy treats the set of `addresses` as a denylist, rejecting any sign transaction to an address that is `not in` the set.
448
+
449
+ ### Transaction limits
450
+
451
+ The following example demonstrates a policy that only permits signing transactions with a value of 2000000000000000000 wei (2 ETH) or less.
452
+
453
+ ```json transaction-limit-policy.json lines wrap
454
+ {
455
+ "description": "Transaction limit policy",
456
+ "scope": "project",
457
+ "rules": [
458
+ {
459
+ "action": "accept",
460
+ "operation": "signEvmTransaction",
461
+ "criteria": [
462
+ {
463
+ "type": "ethValue",
464
+ "ethValue": "2000000000000000000",
465
+ "operator": "<="
466
+ }
467
+ ]
468
+ }
469
+ ]
470
+ }
471
+ ```
472
+
473
+ ### Network restrictions
474
+
475
+ The following example demonstrates a policy that only permits sending transactions on the Base Sepolia network.
476
+
477
+ ```json restricted-network-policy.json lines wrap
478
+ {
479
+ "description": "Restricted network policy",
480
+ "scope": "project",
481
+ "rules": [
482
+ {
483
+ "action": "accept",
484
+ "operation": "sendEvmTransaction",
485
+ "criteria": [
486
+ {
487
+ "type": "evmNetwork",
488
+ "networks": ["base-sepolia"],
489
+ "operator": "in"
490
+ }
491
+ ]
492
+ }
493
+ ]
494
+ }
495
+ ```
496
+
497
+ ### Multi-rule
498
+
499
+ Learn more on combining multiple rules in a single policy.
500
+
501
+ * [**Allowlist first**](#allowlist-first): A policy that checks the allowlist first, then the transaction limit.
502
+ * [**Allowlist second**](#allowlist-second): A policy that checks the transaction value first, then uses a combined rule to check both the transaction value and the allowlist.
503
+
504
+ #### Allowlist first
505
+
506
+ The following example demonstrates a policy that contains both an allowlist and a transaction limit.
507
+
508
+ ```json combined-policy-1.json lines wrap
509
+ {
510
+ "description": "Allowlist then value limit",
511
+ "scope": "project",
512
+ "rules": [
513
+ {
514
+ "action": "accept",
515
+ "operation": "signEvmTransaction",
516
+ "criteria": [
517
+ {
518
+ "type": "evmAddress",
519
+ "addresses": [
520
+ "0xffffffffffffffffffffffffffffffffffffffff"
521
+ ],
522
+ "operator": "in"
523
+ }
524
+ ]
525
+ },
526
+ {
527
+ "action": "accept",
528
+ "operation": "signEvmTransaction",
529
+ "criteria": [
530
+ {
531
+ "type": "ethValue",
532
+ "ethValue": "2000000000000000000",
533
+ "operator": "<="
534
+ }
535
+ ]
536
+ }
537
+ ]
538
+ }
539
+ ```
540
+
541
+ In the example above, assume a user sends a sign transaction request with a value of 4000000000000000000 wei (4 ETH) to the address 0x123:
542
+
543
+ 1. The transaction will be rejected against the first rule, as the address is not in the allowlist. However, the criteria still is not met and the engine will evaluate the transaction against the second rule.
544
+ 2. The transaction will be rejected against the second rule, as the value is greater than 2000000000000000000 wei (2 ETH).
545
+
546
+ #### Allowlist second
547
+
548
+ Let's take a look at another combined policy example where we define the allowlist as the second rule instead of the first.
549
+
550
+ ```json combined-policy-2.json lines wrap
551
+ {
552
+ "description": "Value limit then allowlist",
553
+ "scope": "project",
554
+ "rules": [
555
+ {
556
+ "action": "accept",
557
+ "operation": "signEvmTransaction",
558
+ "criteria": [
559
+ {
560
+ "type": "ethValue",
561
+ "ethValue": "1000000000000000000",
562
+ "operator": "<="
563
+ }
564
+ ]
565
+ },
566
+ {
567
+ "action": "accept",
568
+ "operation": "signEvmTransaction",
569
+ "criteria": [
570
+ {
571
+ "type": "ethValue",
572
+ "ethValue": "2000000000000000000",
573
+ "operator": "<="
574
+ },
575
+ {
576
+ "type": "evmAddress",
577
+ "addresses": [
578
+ "0xffffffffffffffffffffffffffffffffffffffff"
579
+ ],
580
+ "operator": "in"
581
+ }
582
+ ]
583
+ }
584
+ ]
585
+ }
586
+ ```
587
+
588
+ In the above example, if a user sends a transaction with a value of 1500000000000000000 wei (1.5 ETH) to the address 0x123:
589
+
590
+ 1. The transaction will be rejected against the first rule, as the value is greater than 1000000000000000000 wei. However, the criteria still is not met and the engine will continue evaluating the transaction against the second rule.
591
+ 2. The transaction matches against the second rule, as the value is less than or equal to 2000000000000000000 wei **AND** the address is in the allowlist. The transaction will be accepted.
592
+
593
+ <Accordion title="What's the difference?">
594
+ The primary differences between these two examples are the rule order in which a transaction is evaluated.
595
+
596
+ * **The first example checks the allowlist first, and then the transaction limit**
597
+ * This option is more restrictive, as it requires all transactions go to allowlisted addresses first, regardless of their value.
598
+
599
+ * **The second example checks the transaction value first, then uses a combined rule to check both the transaction value and the allowlist**
600
+ * This option offers more granular control by allowing small transactions to be signed to any address, but restricts larger transactions to allowlisted addresses only.
601
+ </Accordion>
602
+
603
+ ### Message signing restrictions
604
+
605
+ The following example demonstrates how to guarantee any attempt to sign a message will conform to a specific template. When composing a regular expression in the `match` field, any valid [re2](https://github.com/google/re2) regular expression syntax will be accepted.
606
+
607
+ ```json accept-sign-message-policy.json lines wrap
608
+ {
609
+ "description": "Accept sign message policy",
610
+ "scope": "project",
611
+ "rules": [
612
+ {
613
+ "action": "accept",
614
+ "operation": "signEvmMessage",
615
+ "criteria": [
616
+ {
617
+ "type": "evmMessage",
618
+ "match": "^I solemnly swear that I,(.*), am up to no good\.$"
619
+ }
620
+ ]
621
+ }
622
+ ]
623
+ }
624
+ ```
625
+
626
+ ### Limiting USDC Spend
627
+
628
+ This policy restricts USDC transactions on the Base network to transfers of 10,000 tokens or less. It applies to both signing and sending transactions to the USDC contract address, using the ERC20 ABI to validate that only `transfer` function calls with a `value` parameter under the specified limit are permitted.
629
+
630
+ ```json limit-usdc-spend-policy.json
631
+ {
632
+ "description": "Limit USDC Spend",
633
+ "scope": "account",
634
+ "rules": [
635
+ {
636
+ "action": "accept",
637
+ "operation": "sendEvmTransaction",
638
+ "criteria": [
639
+ {
640
+ "type": "evmNetwork",
641
+ "networks": ["base"],
642
+ "operator": "in"
643
+ },
644
+ {
645
+ "type": "evmAddress",
646
+ "addresses": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"],
647
+ "operator": "in"
648
+ },
649
+ {
650
+ "type": "evmData",
651
+ "abi": "erc20",
652
+ "conditions": [
653
+ {
654
+ "function": "transfer",
655
+ "params": [
656
+ {
657
+ "name": "value",
658
+ "operator": "<=",
659
+ "value": "10000"
660
+ }
661
+ ]
662
+ }
663
+ ]
664
+ }
665
+ ]
666
+ },
667
+ {
668
+ "action": "accept",
669
+ "operation": "signEvmTransaction",
670
+ "criteria": [
671
+ {
672
+ "type": "evmAddress",
673
+ "addresses": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"],
674
+ "operator": "in"
675
+ },
676
+ {
677
+ "type": "evmData",
678
+ "abi": "erc20",
679
+ "conditions": [
680
+ {
681
+ "function": "transfer",
682
+ "params": [
683
+ {
684
+ "name": "value",
685
+ "operator": "<=",
686
+ "value": "10000"
687
+ }
688
+ ]
689
+ }
690
+ ]
691
+ }
692
+ ]
693
+ }
694
+ ]
695
+ }
696
+ ```
697
+
698
+ ### Disable signing arbitrary hashes
699
+
700
+ The example below demonstrates a policy to prevent fraud by rejecting any attempt to sign a hash (i.e., undefined or arbitrary input data) on behalf of an account.
701
+
702
+ ```json reject-sign-hash-policy.json lines wrap
703
+ {
704
+ "description": "Reject sign hash policy",
705
+ "scope": "project",
706
+ "rules": [
707
+ {
708
+ "action": "reject",
709
+ "operation": "signEvmHash"
710
+ }
711
+ ]
712
+ }
713
+ ```
714
+
715
+ ## Video: Watch and learn
716
+
717
+ Watch the video to learn how to implement and manage policies with CDP Wallet API, which covers:
718
+
719
+ * An overview of policy engine setup and configuration
720
+ * How to create project-level and account-level policies
721
+ * Best practices for implementing transaction controls and security measures
722
+
723
+ <Frame>
724
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/PBgWe345V0w" title="How to implement policies with CDP Wallet API" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen />
725
+ </Frame>
726
+
727
+ ## What to read next
728
+
729
+ * [**v2 Wallet Security**](/wallet-api/v2/introduction/security): Learn more about the security features of the CDP v2 Wallet API.
730
+ * [**v2 API Reference**](/api-reference/v2/rest-api/policy-engine/policy-engine): Explore the API reference for CDP Policies.