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()