Skip to content

Permissioned domains #3102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Permissioned domains #3102

wants to merge 2 commits into from

Conversation

oeggert
Copy link
Collaborator

@oeggert oeggert commented Apr 29, 2025

Add modular tutorial for Permissioned Domains. Includes pending refactors from #3091

@oeggert oeggert requested a review from maria-robobug April 29, 2025 20:40
@oeggert
Copy link
Collaborator Author

oeggert commented Apr 29, 2025

@maria-robobug After #3091 is merged, I'll update whatever changes happened there into this PR. I expect only the code to change on the backend, the frontend functionality and tutorial page should stay the same, so those can be safely reviewed.


[![Create Permissioned Domain Test Harness](/docs/img/create-permissioned-domain-1.png)](/docs/img/create-permissioned-domain-1.png)

Download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/modular-tutorials/)<!-- {.github-code-download} --> folder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we need the comment here?

Suggested change
Download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/modular-tutorials/)<!-- {.github-code-download} --> folder.
Download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/modular-tutorials/).

Comment on lines +15 to +76
try {

// Get account wallet from seed
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)

// Get Domain ID
const domainID = domainIDField.value

// Get credential type - convert string to hex if needed
let credentialType = credentialTypeField.value;
if (!/^[0-9A-F]+$/i.test(credentialType)) {
let hex = '';
for (let i = 0; i < credentialType.length; i++) {
const charCode = credentialType.charCodeAt(i);
const hexCharCode = charCode.toString(16).padStart(2, '0');
hex += hexCharCode;
}
credentialType = hex.toUpperCase();
}

// Prepare transaction
const transaction = {
"TransactionType": "PermissionedDomainSet",
"Account": wallet.address,
"AcceptedCredentials": [
{
"Credential": {
"Issuer": wallet.address,
"CredentialType": credentialType
}
}
]
}

if (domainID) {
transaction.DomainID = domainID
}

results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
updateResults()

// Submit transaction
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})

if (tx.result.meta.TransactionResult == "tesSUCCESS") {
// Parse for domain info
if (domainID) {
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(tx.result.tx_json, null, 2)}`
} else {
const parsedResponse = JSON.parse(JSON.stringify(tx.result.meta.AffectedNodes, null, 2))
const domainInfo = parsedResponse.find( node => node.CreatedNode && node.CreatedNode.LedgerEntryType === "PermissionedDomain" )
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(domainInfo.CreatedNode, null, 2)}`
}
} else {
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/permissioneddomainset#error-cases`
}
updateResults()

} catch (error) {
results = `\n\n===Error===\n\n${error}`
updateResults()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The try-catch formatting needs indentation:

Suggested change
try {
// Get account wallet from seed
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
// Get Domain ID
const domainID = domainIDField.value
// Get credential type - convert string to hex if needed
let credentialType = credentialTypeField.value;
if (!/^[0-9A-F]+$/i.test(credentialType)) {
let hex = '';
for (let i = 0; i < credentialType.length; i++) {
const charCode = credentialType.charCodeAt(i);
const hexCharCode = charCode.toString(16).padStart(2, '0');
hex += hexCharCode;
}
credentialType = hex.toUpperCase();
}
// Prepare transaction
const transaction = {
"TransactionType": "PermissionedDomainSet",
"Account": wallet.address,
"AcceptedCredentials": [
{
"Credential": {
"Issuer": wallet.address,
"CredentialType": credentialType
}
}
]
}
if (domainID) {
transaction.DomainID = domainID
}
results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
updateResults()
// Submit transaction
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})
if (tx.result.meta.TransactionResult == "tesSUCCESS") {
// Parse for domain info
if (domainID) {
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(tx.result.tx_json, null, 2)}`
} else {
const parsedResponse = JSON.parse(JSON.stringify(tx.result.meta.AffectedNodes, null, 2))
const domainInfo = parsedResponse.find( node => node.CreatedNode && node.CreatedNode.LedgerEntryType === "PermissionedDomain" )
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(domainInfo.CreatedNode, null, 2)}`
}
} else {
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/permissioneddomainset#error-cases`
}
updateResults()
} catch (error) {
results = `\n\n===Error===\n\n${error}`
updateResults()
}
try {
// Get account wallet from seed
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
// Get Domain ID
const domainID = domainIDField.value
// Get credential type - convert string to hex if needed
let credentialType = credentialTypeField.value;
if (!/^[0-9A-F]+$/i.test(credentialType)) {
let hex = '';
for (let i = 0; i < credentialType.length; i++) {
const charCode = credentialType.charCodeAt(i);
const hexCharCode = charCode.toString(16).padStart(2, '0');
hex += hexCharCode;
}
credentialType = hex.toUpperCase();
}
// Prepare transaction
const transaction = {
"TransactionType": "PermissionedDomainSet",
"Account": wallet.address,
"AcceptedCredentials": [
{
"Credential": {
"Issuer": wallet.address,
"CredentialType": credentialType
}
}
]
}
if (domainID) {
transaction.DomainID = domainID
}
results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
updateResults()
// Submit transaction
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})
if (tx.result.meta.TransactionResult == "tesSUCCESS") {
// Parse for domain info
if (domainID) {
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(tx.result.tx_json, null, 2)}`
} else {
const parsedResponse = JSON.parse(JSON.stringify(tx.result.meta.AffectedNodes, null, 2))
const domainInfo = parsedResponse.find( node => node.CreatedNode && node.CreatedNode.LedgerEntryType === "PermissionedDomain" )
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(domainInfo.CreatedNode, null, 2)}`
}
} else {
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/permissioneddomainset#error-cases`
}
updateResults()
} catch (error) {
results = `\n\n===Error===\n\n${error}`
updateResults()
}


// Get credential type - convert string to hex if needed
let credentialType = credentialTypeField.value;
if (!/^[0-9A-F]+$/i.test(credentialType)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use convenience functions from the @xrplf/isomorphic package to convert string to hex or hex back to string: stringToHex, hexToString.

Also mentioned in xrpl.js reference:
https://js.xrpl.org/functions/convertStringToHex.html
https://js.xrpl.org/functions/convertHexToString.html


Define a function that creates a permissioned domain.

```javascript
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a question I had in the other PR as well, more for my own benefit to understand which approach we want to go with.

Shouldn't we be referencing code snippets like this now?

{% code-snippet file="/_code-samples/modular-tutorials/send-checks.js" language="js" from="async function sendCheck() {" before="let check_amount = amountField.value" /%}

2. Copy the _LedgerIndex_ value from the metadata response.
3. (Optional) Update the permissioned domain with a different credential.
1. Change the **Credential Type**.
2. Click **Create Credential**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. Click **Create Credential**
2. Click **Create Credential**.

## Delete a Permissioned Domain

1. Copy the _LedgerIndex_ value into **DomainID**.
2. Click **Delete Permissioned Domain**..
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. Click **Delete Permissioned Domain**..
2. Click **Delete Permissioned Domain**.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants