mirror of
				https://github.com/XRPLF/xrpl-dev-portal.git
				synced 2025-11-04 03:45:49 +00:00 
			
		
		
		
	More Permission Delegation edits per review
This commit is contained in:
		@@ -10,15 +10,7 @@ These code samples demonstrate how to delegate permissions to another account an
 | 
			
		||||
    npm i
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
2. Go to the [XRP Faucet](https://xrpl.org/resources/dev-tools/xrp-faucets) and generate a **Devnet** account to be your delegate account.
 | 
			
		||||
 | 
			
		||||
3. Edit `delegate-permisions.js` and change the following line to use the address you got from the faucet:
 | 
			
		||||
 | 
			
		||||
    ```js
 | 
			
		||||
        const delegate_address = "r9GAKojMTyexqvy8DXFWYq63Mod5k5wnkT"
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
4. Run `delegate-permissions.js`.
 | 
			
		||||
2. Run `delegate-permisions.js`.
 | 
			
		||||
 | 
			
		||||
    ```sh
 | 
			
		||||
    node delegate-permissions.js
 | 
			
		||||
@@ -26,9 +18,9 @@ These code samples demonstrate how to delegate permissions to another account an
 | 
			
		||||
 | 
			
		||||
    If it runs successfully, it should output several things including "Delegate successfully set." followed by an [account_objects API method](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_objects) response showing the delegate permissions.
 | 
			
		||||
 | 
			
		||||
    Take note of the `account` address in this output. That's the address of the delegator.
 | 
			
		||||
    Take note of the **Delegator address** and **Delegate seed** from the output.
 | 
			
		||||
 | 
			
		||||
5. Run `use-delegate-permissions.js` and provide both the delegator's address (from the previous step's output) and the delegate's secret key (from the devnet faucet earlier).
 | 
			
		||||
3. Run `use-delegate-permissions.js` and provide both the delegator's address and the delegate's secret key that were output in the previous step.
 | 
			
		||||
 | 
			
		||||
    If it runs successfully, it should output various things ending in the following:
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -4,15 +4,21 @@ async function main() {
 | 
			
		||||
    const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
 | 
			
		||||
    await client.connect()
 | 
			
		||||
 | 
			
		||||
    console.log("Funding new wallet from faucet...")
 | 
			
		||||
    const { wallet } = await client.fundWallet()
 | 
			
		||||
    console.log("Funding new wallets from faucet...")
 | 
			
		||||
    const delegator_wallet = (await client.fundWallet()).wallet
 | 
			
		||||
    console.log("Delegator account:")
 | 
			
		||||
    console.log("  Address:", delegator_wallet.address)
 | 
			
		||||
    const delegate_wallet = (await client.fundWallet()).wallet
 | 
			
		||||
    console.log("Delegate account:")
 | 
			
		||||
    console.log("  Address:", delegate_wallet.address)
 | 
			
		||||
    console.log("  Seed:", delegate_wallet.seed)
 | 
			
		||||
    console.log("Please note these values for later.")
 | 
			
		||||
 | 
			
		||||
    // Define the transaction
 | 
			
		||||
    const delegate_address = "r9GAKojMTyexqvy8DXFWYq63Mod5k5wnkT"
 | 
			
		||||
    const delegateset = {
 | 
			
		||||
        "TransactionType": "DelegateSet",
 | 
			
		||||
        "Account": wallet.address, // Delegator address
 | 
			
		||||
        "Authorize": delegate_address,
 | 
			
		||||
        "Account":   delegator_wallet.address,
 | 
			
		||||
        "Authorize": delegate_wallet.address,
 | 
			
		||||
        "Permissions": [
 | 
			
		||||
            {
 | 
			
		||||
                "Permission": {
 | 
			
		||||
@@ -23,9 +29,10 @@ async function main() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare, sign, and submit the transaction
 | 
			
		||||
    const prepared = await client.autofill(delegateset)
 | 
			
		||||
    const signed = wallet.sign(prepared)
 | 
			
		||||
    const result = await client.submitAndWait(signed.tx_blob)
 | 
			
		||||
    const result = await client.submitAndWait(delegateset, {
 | 
			
		||||
        wallet: delegator_wallet,
 | 
			
		||||
        autofill: true
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Check transaction results
 | 
			
		||||
    console.log(result)
 | 
			
		||||
@@ -36,7 +43,7 @@ async function main() {
 | 
			
		||||
    // Confirm presence of Delegate ledger entry using account_objects
 | 
			
		||||
    response = await client.request({
 | 
			
		||||
        "command": "account_objects",
 | 
			
		||||
        "account": wallet.address,
 | 
			
		||||
        "account": delegator_wallet.address,
 | 
			
		||||
        "type": "delegate",
 | 
			
		||||
        "ledger_index": "validated"
 | 
			
		||||
    })
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@ const readline = require('readline').createInterface({
 | 
			
		||||
})
 | 
			
		||||
const { stringToHex, hexToString } = require('@xrplf/isomorphic/utils')
 | 
			
		||||
 | 
			
		||||
// Set delegating account and delegate from user input
 | 
			
		||||
readline.question(`Address of delegating account? `, async function(from_address) {
 | 
			
		||||
  readline.question(`Delegate's secret key? `, async function(secret) {
 | 
			
		||||
// Get delegator and delegate accounts from user input
 | 
			
		||||
readline.question(`Delegator's address? `, async function(delegator_address) {
 | 
			
		||||
  readline.question(`Delegate's seed? `, async function(secret) {
 | 
			
		||||
    const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
 | 
			
		||||
    await client.connect()
 | 
			
		||||
 | 
			
		||||
@@ -17,13 +17,15 @@ readline.question(`Address of delegating account? `, async function(from_address
 | 
			
		||||
    // Check which permissions the delegate has been granted, if any
 | 
			
		||||
    response = await client.request({
 | 
			
		||||
        "command": "account_objects",
 | 
			
		||||
        "account": from_address,
 | 
			
		||||
        "account": delegator_address,
 | 
			
		||||
        "type": "delegate",
 | 
			
		||||
        "ledger_index": "validated"
 | 
			
		||||
    })
 | 
			
		||||
    let found_match = false
 | 
			
		||||
    for (delegate_entry of response.result.account_objects) {
 | 
			
		||||
      if (delegate_entry.Account == from_address && delegate_entry.Authorize == delegate_wallet.address) {
 | 
			
		||||
      if (delegate_entry.Account == delegator_address && 
 | 
			
		||||
          delegate_entry.Authorize == delegate_wallet.address) {
 | 
			
		||||
 | 
			
		||||
        found_match = true
 | 
			
		||||
        console.log("Delegate has the following permissions:")
 | 
			
		||||
        for (perm of delegate_entry.Permissions) {
 | 
			
		||||
@@ -33,26 +35,29 @@ readline.question(`Address of delegating account? `, async function(from_address
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (!found_match) {
 | 
			
		||||
      console.warn("Delegate appears not to have any permissions granted by delegating account.")
 | 
			
		||||
      console.warn("Did you run delegate-permissions.js first with your delegate address?")
 | 
			
		||||
      console.warn("Delegate appears not to have any permissions granted"+
 | 
			
		||||
                   " by the delegator.")
 | 
			
		||||
      console.warn("Make sure you ran delegate-permissions.js and input the"+
 | 
			
		||||
                   " correct delegate/delegator values to this script.")
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Use the AccountDomainSet granular permission to set the "Domain" field
 | 
			
		||||
    // of the delegating account
 | 
			
		||||
    // of the delegator
 | 
			
		||||
    const set_domain_example = {
 | 
			
		||||
      "TransactionType": "AccountSet",
 | 
			
		||||
      "Account": from_address,
 | 
			
		||||
      "Account": delegator_address,
 | 
			
		||||
      "Delegate": delegate_wallet.address,
 | 
			
		||||
      "Domain": stringToHex("example.com")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare, sign, and submit the transaction
 | 
			
		||||
    const prepared = await client.autofill(set_domain_example)
 | 
			
		||||
    const signed = delegate_wallet.sign(prepared)
 | 
			
		||||
    console.log("Submitting transaction:")
 | 
			
		||||
    console.log(JSON.stringify(signed, null, 2))
 | 
			
		||||
    const result = await client.submitAndWait(signed.tx_blob)
 | 
			
		||||
    console.log(set_domain_example)
 | 
			
		||||
    const result = await client.submitAndWait(set_domain_example, {
 | 
			
		||||
      wallet: delegate_wallet,
 | 
			
		||||
      autofill: true
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Check transaction results and disconnect
 | 
			
		||||
    console.log(result)
 | 
			
		||||
@@ -61,14 +66,15 @@ readline.question(`Address of delegating account? `, async function(from_address
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Confirm that the account's Domain field has been set as expected
 | 
			
		||||
    const account_info_resp = await client.request({
 | 
			
		||||
    const acct_info_resp = await client.request({
 | 
			
		||||
      "command": "account_info",
 | 
			
		||||
      "account": from_address,
 | 
			
		||||
      "account": delegator_address,
 | 
			
		||||
      "ledger_index": "validated"
 | 
			
		||||
    })
 | 
			
		||||
    const domain_str = hexToString(account_info_resp.result.account_data.Domain)
 | 
			
		||||
    const domain_str = hexToString(acct_info_resp.result.account_data.Domain)
 | 
			
		||||
    console.log(`Domain is ${domain_str}`)
 | 
			
		||||
 | 
			
		||||
    client.disconnect()
 | 
			
		||||
    readline.close()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -8,24 +8,25 @@ status: not_enabled
 | 
			
		||||
---
 | 
			
		||||
# Permission Delegation
 | 
			
		||||
 | 
			
		||||
Permission delegation is the function of granting various permissions to another account to send permissions on behalf of your account. This can be used instead of or alongside techniques such as [multi-signing](./multi-signing.md) to enable flexible security paradigms such as role-based access control.
 | 
			
		||||
Permission delegation is the function of granting various permissions to another account to send permissions on behalf of your account. You can use permission delegation to enable flexible security paradigms such as role-based access control, instead of or alongside techniques such as [multi-signing](./multi-signing.md).
 | 
			
		||||
 | 
			
		||||
_(Requires the [PermissionDelegation amendment][] {% not-enabled /%}.)_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Background
 | 
			
		||||
 | 
			
		||||
Managing your [cryptographic keys](./cryptographic-keys.md) is one of the more challenging parts of using a blockchain. As part of a defense-in-depth strategy, a secure configuration should limit the damage that can occur if a secret key is compromised. One way to do this is to rotate keys regularly and to keep master keys off of computers that are always connected to the internet and serving user traffic. However, many use cases involve frequently and automatically signing transactions, which typically necessitates having secret keys on an internet-connected server.
 | 
			
		||||
Managing your [cryptographic keys](./cryptographic-keys.md) is one of the more challenging parts of using a blockchain. As part of a defense-in-depth strategy, a secure configuration should limit the damage that can occur if a secret key is compromised. One way to do this is to rotate keys regularly and to keep master keys off of computers that are always connected to the internet and serving user traffic. However, many use cases involve frequently and automatically signing transactions, which typically requires having secret keys on an internet-connected server.
 | 
			
		||||
 | 
			
		||||
Permission Delegation can help optimize for these sorts of challenges by granting very limited permissions to separate accounts that can have their keys available online, while keeping the master keys for the main account offline and only using them manually in special cases when rare, important tasks like issuing tokens are necessary. This is especially helpful when using compliance features like [Authorized Trust Lines](../tokens/fungible-tokens/authorized-trust-lines.md) that require a stablecoin issuer to individually approve each user after meeting regulatory requirements like Know Your Customer rules. With a proper configuration, the keys that are used to approve users cannot be used to perform other actions like issuing new tokens or rotating the issuer's key pairs.
 | 
			
		||||
Permission Delegation can reduce this problem by granting very limited permissions to separate accounts that have their keys available online for day-to-day tasks. Meanwhile, the keys with full control over the account can be kept offline, so that you only use them for special tasks, like issuing tokens. This is especially helpful when using compliance features like [Authorized Trust Lines](../tokens/fungible-tokens/authorized-trust-lines.md) that require a stablecoin issuer to individually approve each user after meeting regulatory requirements like Know Your Customer rules. With a proper configuration, you can minimize the consequences of a delegate's keys being compromized.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## How It Works
 | 
			
		||||
 | 
			
		||||
The account on whose behalf transactions are being sent is called the _delegating account_. The account sending the transactions is called the _delegate_.
 | 
			
		||||
The account on whose behalf transactions are being sent is called the _delegator_. The account sending the transactions is called the _delegate_.
 | 
			
		||||
 | 
			
		||||
The delegating account first sends a [DelegateSet transaction][] to designate an account as its delegate and to specify which permissions the delegate has. The delegating account can update or revoke the permissions at any time by sending another DelegateSet transaction. A delegating account can have more than one delegate, and can grant different sets of permissions to each delegate.
 | 
			
		||||
The delegator first sends a [DelegateSet transaction][] to designate an account as its delegate and to specify which permissions the delegate has. The delegator can update or revoke the permissions at any time by sending another DelegateSet transaction. A delegator can have more than one delegate, and can grant different sets of permissions to each delegate.
 | 
			
		||||
 | 
			
		||||
A delegate can send transactions that execute as if they were sent by the delegating account. These transactions specify both the delegating account's information as well as the address of the delegate who is sending the transaction. The delegate can sign these transactions with any of the following:
 | 
			
		||||
A delegate can send transactions that execute as if they were sent by the delegator. These transactions specify both the delegator's information as well as the address of the delegate who is sending the transaction. The delegate can sign these transactions with any of the following:
 | 
			
		||||
 | 
			
		||||
- The delegate's master key pair
 | 
			
		||||
- A regular key pair that the delegate has authorized
 | 
			
		||||
@@ -40,7 +41,7 @@ For a complete list of transaction types that can or cannot be delegated as well
 | 
			
		||||
 | 
			
		||||
### Limitations
 | 
			
		||||
 | 
			
		||||
The main limiting factor on how many delegates you can have is that you must hold enough XRP to meet the [reserve requirement](./reserves.md). Each delegate's permissions are tracked with a [Delegate ledger entry][], which counts as one item towards the delegating account's owner reserve.
 | 
			
		||||
The main limiting factor on how many delegates you can have is that you must hold enough XRP to meet the [reserve requirement](./reserves.md). Each delegate's permissions are tracked with a [Delegate ledger entry][], which counts as one item towards the delegator's owner reserve.
 | 
			
		||||
 | 
			
		||||
Each delegate can be granted up to 10 permissions.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user