Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.DS_Store
_code-samples/*/js/package-lock.json
_code-samples/*/js/*[Ss]etup.json
32 changes: 17 additions & 15 deletions _code-samples/vaults/js/createVault.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import xrpl from "xrpl"
import { execSync } from "child_process"
import fs from "fs"

// Connect to the network ----------------------
// This is a lending protocol-specific devnet. This network may be taken
// offline once the lending protocol is live on mainnet.
const client = new xrpl.Client("wss://lend.devnet.rippletest.net:51233")
await client.connect()
// Auto-run setup if needed
if (!fs.existsSync("vaultSetup.json")) {
console.log(`\n=== Vault setup data doesn't exist. Running setup script... ===\n`)
execSync("node vaultSetup.js", { stdio: "inherit" })
}

// Use the Lending Devnet faucet
const faucetHost = "lend-faucet.devnet.rippletest.net"
const faucetPath = "/accounts"
// Load setup data
const setupData = JSON.parse(fs.readFileSync("vaultSetup.json", "utf8"))

// Create and fund vault owner account
const { wallet: vaultOwner } = await client.fundWallet(null, { faucetHost, faucetPath })
// Connect to the network
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
await client.connect()

// A pre-existing Vault asset, created for this tutorial. You can specify your own Vault asset.
const mptIssuanceId = "0003E3B486D3DACD8BB468AB33793B9626BD894A92AB3AB4"
// Create and fund vault owner account
const { wallet: vaultOwner } = await client.fundWallet()

// A pre-existing Permissioned Domain ID, created for this tutorial. You can specify your own Domain ID.
// NOTE: You don't need this if you want to create a public vault.
const domainId = "3BB81D0D164456A2D74720F63FD923F16DE08FB3223D3ED103D09F525A8D69D1"
// You can replace these values with your own
const mptIssuanceId = setupData.mptIssuanceId
const domainId = setupData.domainId

console.log(`Vault owner address: ${vaultOwner.address}`)
console.log(`MPT issuance ID: ${mptIssuanceId}`)
Expand Down
30 changes: 18 additions & 12 deletions _code-samples/vaults/js/deposit.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@
// values with your own.

import xrpl from "xrpl"
import { execSync } from "child_process"
import fs from "fs"

// Connect to the network ----------------------
// This is a lending protocol-specific devnet. This network may be taken
// offline once the lending protocol is live on mainnet.
const client = new xrpl.Client("wss://lend.devnet.rippletest.net:51233")
await client.connect()
// Auto-run setup if needed
if (!fs.existsSync("vaultSetup.json")) {
console.log(`\n=== Vault setup data doesn't exist. Running setup script... ===\n`)
execSync("node vaultSetup.js", { stdio: "inherit" })
}

const depositor = xrpl.Wallet.fromSeed("sEdVSq9Zsv8vQwfivTk37bWxrvpnruf")
// Load setup data
const setupData = JSON.parse(fs.readFileSync("vaultSetup.json", "utf8"))

// Connect to the network
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
await client.connect()

// The ID of the vault to deposit into
const vaultID = "6AC4EC2D775C6275D314996D6ECDD16DCB9382A29FDB769951C42192FCED76EF"
// The ID of the vault's asset (MPT Issuance)
const assetMPTIssuanceId = "0003E3B486D3DACD8BB468AB33793B9626BD894A92AB3AB4"
// The ID of the vault's share (MPT Issuance)
const shareMPTIssuanceId = "0000000152E7CD364F869E832EDB806C4A7AD8B3D0C151C5"
// You can replace these values with your own
const depositor = xrpl.Wallet.fromSeed(setupData.depositor.seed)
const vaultID = setupData.vaultID
const assetMPTIssuanceId = setupData.mptIssuanceId
const shareMPTIssuanceId = setupData.vaultShareMPTIssuanceId

console.log(`Depositor address: ${depositor.address}`)
console.log(`Vault ID: ${vaultID}`)
Expand Down
2 changes: 1 addition & 1 deletion _code-samples/vaults/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vault-examples",
"description": "Example code for creating and managing vaults",
"dependencies": {
"xrpl": "^4.4.3"
"xrpl": "^4.5.0"
},
"type": "module"
}
262 changes: 262 additions & 0 deletions _code-samples/vaults/js/vaultSetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
import xrpl from 'xrpl'
import fs from 'fs'

// Setup script for vault tutorials

process.stdout.write('Setting up tutorial: 0/5\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/5\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/5\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/5\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/6\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/6\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('Private vault for tutorials'),
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()
25 changes: 17 additions & 8 deletions _code-samples/vaults/js/withdraw.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import xrpl from "xrpl"
import { execSync } from "child_process"
import fs from "fs"

// Connect to the network ----------------------
// This is a lending protocol-specific devnet. This network may be taken
// offline once the lending protocol is live on mainnet.
const client = new xrpl.Client("wss://lend.devnet.rippletest.net:51233")
// Auto-run setup if needed
if (!fs.existsSync("vaultSetup.json")) {
console.log(`\n=== Vault setup data doesn't exist. Running setup script... ===\n`)
execSync("node vaultSetup.js", { stdio: "inherit" })
}

// Load setup data
const setupData = JSON.parse(fs.readFileSync("vaultSetup.json", "utf8"))

// Connect to the network
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
await client.connect()

// Get depositor account
const depositor = xrpl.Wallet.fromSeed("sEdVSq9Zsv8vQwfivTk37bWxrvpnruf")
const depositor = xrpl.Wallet.fromSeed(setupData.depositor.seed)

// The ID of the vault to withraw from
const vaultID = "6AC4EC2D775C6275D314996D6ECDD16DCB9382A29FDB769951C42192FCED76EF"
const vaultID = setupData.vaultID
// The ID of the vault's asset (MPT Issuance)
const assetMPTIssuanceId = "0003E3B486D3DACD8BB468AB33793B9626BD894A92AB3AB4"
const assetMPTIssuanceId = setupData.mptIssuanceId
// The ID of the vault's share (MPT Issuance)
const shareMPTIssuanceId = "0000000152E7CD364F869E832EDB806C4A7AD8B3D0C151C5"
const shareMPTIssuanceId = setupData.vaultShareMPTIssuanceId

console.log(`Depositor address: ${depositor.address}`)
console.log(`Vault ID: ${vaultID}`)
Expand Down
Loading