Files
xrpl-dev-portal/_code-samples/vaults/js/vaultSetup.js
2026-01-29 21:48:35 +00:00

265 lines
6.8 KiB
JavaScript

import xrpl from 'xrpl'
import fs from 'fs'
// Setup script for vault tutorials
process.stdout.write('Setting up tutorial: 0/7\r')
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
// Create and fund all wallets
const [
{ wallet: mptIssuer },
{ wallet: domainOwner },
{ wallet: depositor },
{ wallet: vaultOwner }
] = await Promise.all([
client.fundWallet(),
client.fundWallet(),
client.fundWallet(),
client.fundWallet()
])
// Step 1: Create MPT issuance
process.stdout.write('Setting up tutorial: 1/7\r')
const mptCreateResult = await client.submitAndWait(
{
TransactionType: 'MPTokenIssuanceCreate',
Account: mptIssuer.address,
Flags:
xrpl.MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
xrpl.MPTokenIssuanceCreateFlags.tfMPTCanLock,
AssetScale: 2,
TransferFee: 0,
MaximumAmount: '1000000000000',
MPTokenMetadata: xrpl.encodeMPTokenMetadata({
ticker: 'USTST',
name: 'USTST Stablecoin',
desc: 'A test stablecoin token',
icon: 'example.org/ustst-icon.png',
asset_class: 'rwa',
asset_subclass: 'stablecoin',
issuer_name: 'Test Stablecoin Inc',
uris: [
{
uri: 'example.org/ustst',
category: 'website',
title: 'USTST Official Website'
},
{
uri: 'example.org/ustst/reserves',
category: 'attestation',
title: 'Reserve Attestation Reports'
},
{
uri: 'example.org/ustst/docs',
category: 'docs',
title: 'USTST Documentation'
}
],
additional_info: {
backing: 'USD',
reserve_ratio: '1:1'
}
})
},
{ wallet: mptIssuer, autofill: true }
)
const mptIssuanceId = mptCreateResult.result.meta.mpt_issuance_id
// Step 2: Create Permissioned Domain
process.stdout.write('Setting up tutorial: 2/7\r')
const credType = 'VaultAccess'
const domainResult = await client.submitAndWait(
{
TransactionType: 'PermissionedDomainSet',
Account: domainOwner.address,
AcceptedCredentials: [
{
Credential: {
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType)
}
}
]
},
{ wallet: domainOwner, autofill: true }
)
const domainId = domainResult.result.meta.AffectedNodes.find(
(node) => node.CreatedNode?.LedgerEntryType === 'PermissionedDomain'
).CreatedNode.LedgerIndex
// Step 3: Create depositor account with credentials and MPT balance
process.stdout.write('Setting up tutorial: 3/7\r')
await Promise.all([
client.submitAndWait(
{
TransactionType: 'CredentialCreate',
Account: domainOwner.address,
Subject: depositor.address,
CredentialType: xrpl.convertStringToHex(credType)
},
{ wallet: domainOwner, autofill: true }
),
client.submitAndWait(
{
TransactionType: 'Batch',
Account: depositor.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
{
RawTransaction: {
TransactionType: 'CredentialAccept',
Account: depositor.address,
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType),
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'MPTokenAuthorize',
Account: depositor.address,
MPTokenIssuanceID: mptIssuanceId,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
}
]
},
{ wallet: depositor, autofill: true }
)
])
process.stdout.write('Setting up tutorial: 4/7\r')
const paymentResult = await client.submitAndWait(
{
TransactionType: 'Payment',
Account: mptIssuer.address,
Destination: depositor.address,
Amount: {
mpt_issuance_id: mptIssuanceId,
value: '10000'
}
},
{ wallet: mptIssuer, autofill: true }
)
if (paymentResult.result.meta.TransactionResult !== 'tesSUCCESS') {
console.error('\nPayment failed:', paymentResult.result.meta.TransactionResult)
await client.disconnect()
process.exit(1)
}
// Step 5: Create a vault for deposit/withdraw examples
process.stdout.write('Setting up tutorial: 5/7\r')
const vaultCreateResult = await client.submitAndWait(
{
TransactionType: 'VaultCreate',
Account: vaultOwner.address,
Asset: {
mpt_issuance_id: mptIssuanceId
},
Flags: xrpl.VaultCreateFlags.tfVaultPrivate,
DomainID: domainId,
Data: xrpl.convertStringToHex(
JSON.stringify({ n: "LATAM Fund II", w: "examplefund.com" })
),
MPTokenMetadata: xrpl.encodeMPTokenMetadata({
ticker: 'SHARE1',
name: 'Vault Shares',
desc: 'Proportional ownership shares of the vault',
icon: 'example.com/vault-shares-icon.png',
asset_class: 'defi',
issuer_name: 'Vault Owner',
uris: [
{
uri: 'example.com/asset',
category: 'website',
title: 'Asset Website'
},
{
uri: 'example.com/docs',
category: 'docs',
title: 'Docs'
}
],
additional_info: {
example_info: 'test'
}
}),
AssetsMaximum: '0',
WithdrawalPolicy:
xrpl.VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe
},
{ wallet: vaultOwner, autofill: true }
)
const vaultNode = vaultCreateResult.result.meta.AffectedNodes.find(
(node) => node.CreatedNode?.LedgerEntryType === 'Vault'
)
const vaultID = vaultNode.CreatedNode.LedgerIndex
const vaultShareMPTIssuanceId = vaultNode.CreatedNode.NewFields.ShareMPTID
// Step 6: Make an initial deposit so withdraw example has shares to work with
process.stdout.write('Setting up tutorial: 6/7\r')
const initialDepositResult = await client.submitAndWait(
{
TransactionType: 'VaultDeposit',
Account: depositor.address,
VaultID: vaultID,
Amount: {
mpt_issuance_id: mptIssuanceId,
value: '1000'
}
},
{ wallet: depositor, autofill: true }
)
if (initialDepositResult.result.meta.TransactionResult !== 'tesSUCCESS') {
console.error('\nInitial deposit failed:', initialDepositResult.result.meta.TransactionResult)
await client.disconnect()
process.exit(1)
}
// Step 7: Save setup data to file
process.stdout.write('Setting up tutorial: 7/7\r')
const setupData = {
mptIssuer: {
address: mptIssuer.address,
seed: mptIssuer.seed
},
mptIssuanceId,
domainOwner: {
address: domainOwner.address,
seed: domainOwner.seed
},
domainId,
credentialType: credType,
depositor: {
address: depositor.address,
seed: depositor.seed
},
vaultOwner: {
address: vaultOwner.address,
seed: vaultOwner.seed
},
vaultID,
vaultShareMPTIssuanceId
}
fs.writeFileSync('vaultSetup.json', JSON.stringify(setupData, null, 2))
process.stdout.write('Setting up tutorial: Complete!\n')
await client.disconnect()