Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
496b8ef
updated Escrow ledger entry type
florent-uzio Sep 25, 2025
23beecb
AccountRoot updated
florent-uzio Sep 25, 2025
f0b58c6
EscrowCreate Amount updated and tests
florent-uzio Sep 26, 2025
f410287
LockedAmount in MPTokenIssuance
florent-uzio Sep 26, 2025
57b1b9f
payment channel create updated
florent-uzio Sep 26, 2025
f65fb81
payment channel claim Amount and Balance updated
florent-uzio Sep 26, 2025
904c2e4
payment channel create, added tests for flatten with iou and mpt
florent-uzio Sep 26, 2025
5432375
Payment channel unmarshal and tests
florent-uzio Sep 26, 2025
766d5fc
Added the asfAllowTrustLineLocking flag
florent-uzio Sep 26, 2025
58c47f1
fixed flatten fields for escrow .String()
florent-uzio Sep 26, 2025
6bba89b
updated TxResponse to handle TxJson field and Sequence
florent-uzio Sep 26, 2025
fc5524f
TokenEscrow rpc example IOU and update PermissionedDex
florent-uzio Sep 26, 2025
f162d79
WS TokenEscrow example and updated Sequence func in flat_tx.go
florent-uzio Sep 26, 2025
e9bdb14
changelog
florent-uzio Sep 26, 2025
0e9420f
renamed TxJson to TxJSON
florent-uzio Sep 26, 2025
7f897bc
fixed linting for integer overflow
florent-uzio Sep 26, 2025
15bc88a
domain.go added ignore linting error from revive
florent-uzio Sep 26, 2025
27df013
TestAccountRoot_SetLsfAllowTrustLineLocking
florent-uzio Oct 16, 2025
f797ce7
reverted payment channel create amount type
florent-uzio Oct 16, 2025
35c1f96
channel claim reverted
florent-uzio Oct 16, 2025
5a47fdc
channel fund reverted
florent-uzio Oct 16, 2025
50a2667
updated claim comments and test name
florent-uzio Oct 16, 2025
1c16391
Added Optional to claim comment
florent-uzio Oct 16, 2025
5e106b9
space claim comment total
florent-uzio Oct 16, 2025
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
#### xrpl

- Adds `PermissionedDomain` ledger entry type (XLS-80d).
- Adds `TokenEscrow` support (XLS-85).

### Fixed

- Flatten function in Escrow transaction types for Destination and Owner fields.

## [v0.1.11]

Expand Down
2 changes: 1 addition & 1 deletion examples/permissioned-dex/ws/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ func main() {
return
}

offerNode := txResponse.Tx
offerNode := txResponse.TxJSON
fmt.Printf("✅ Offer ledger object retrieved\n")
fmt.Printf(" 📊 LedgerEntryType: %v\n", offerNode["LedgerEntryType"])
fmt.Printf(" 🏷️ DomainID: %v\n", offerNode["DomainID"])
Expand Down
271 changes: 271 additions & 0 deletions examples/token-escrow/rpc/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
package main

import (
"fmt"
"time"

"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/currency"

"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
rippleTime "github.com/Peersyst/xrpl-go/xrpl/time"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)

// safeInt64ToUint32 safely converts int64 to uint32 with bounds checking
func safeInt64ToUint32(value int64) uint32 {
if value < 0 {
return 0
}
if value > int64(^uint32(0)) {
return ^uint32(0) // max uint32 value
}
return uint32(value)
}

func main() {

//
// Configure client
//
fmt.Println("⏳ Setting up client...")
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}

client := rpc.NewClient(cfg)
fmt.Println("✅ Client configured!")
fmt.Println()

// Configure wallets
issuerWallet, holderWallet, holderWallet2 := createWallets(client)

// Configure issuer wallet to allow trust line locking
configureIssuerWallet(client, issuerWallet)

// Create trust line from holder to issuer
createTrustLine(client, issuerWallet, holderWallet, holderWallet2)

// Mint token from issuer to holder
mintToken(client, issuerWallet, holderWallet)

// Create escrow, the holder will escrow 100 tokens to the issuer
offerSequence := createEscrow(client, issuerWallet, holderWallet, holderWallet2)

// Finish escrow
finishEscrow(client, holderWallet, holderWallet2, offerSequence)
}

// createWallets configures the issuer and holder wallets.
func createWallets(client *rpc.Client) (issuerWallet, holderWallet, holderWallet2 wallet.Wallet) {
fmt.Println("⏳ Setting up wallets...")
issuerWallet, err := wallet.New(crypto.ED25519())
if err != nil {
fmt.Printf("❌ Error creating issuer wallet: %s\n", err)
return
}
err = client.FundWallet(&issuerWallet)
if err != nil {
fmt.Printf("❌ Error funding issuer wallet: %s\n", err)
return
}
fmt.Println("💸 Issuer wallet funded!")

// Holder wallet
holderWallet, err = wallet.New(crypto.ED25519())
if err != nil {
fmt.Printf("❌ Error creating holder wallet: %s\n", err)
return
}
err = client.FundWallet(&holderWallet)
if err != nil {
fmt.Printf("❌ Error funding holder wallet: %s\n", err)
return
}
fmt.Println("💸 Holder wallet funded!")

// Holder wallet 2
holderWallet2, err = wallet.New(crypto.ED25519())
if err != nil {
fmt.Printf("❌ Error creating holder wallet 2: %s\n", err)
return
}
err = client.FundWallet(&holderWallet2)
if err != nil {
fmt.Printf("❌ Error funding holder wallet 2: %s\n", err)
return
}
fmt.Println("💸 Holder wallet 2 funded!")

fmt.Println("✅ Wallets setup complete!")
fmt.Println("💳 Issuer wallet:", issuerWallet.ClassicAddress)
fmt.Println("💳 Holder wallet:", holderWallet.ClassicAddress)
fmt.Println("💳 Holder wallet 2:", holderWallet2.ClassicAddress)
fmt.Println()

return issuerWallet, holderWallet, holderWallet2
}

// configureIssuerWallet configures the issuer wallet to allow trust line locking.
func configureIssuerWallet(client *rpc.Client, issuerWallet wallet.Wallet) {
fmt.Println("⏳ Configuring issuer wallet...")
accountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: issuerWallet.ClassicAddress,
},
}
accountSet.SetAsfAllowTrustLineLocking()
accountSetResponse, err := client.SubmitTxAndWait(accountSet.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &issuerWallet,
})
if err != nil {
fmt.Printf("❌ Error configuring issuer wallet: %s\n", err)
return
}
fmt.Println("✅ Issuer wallet configured!")
fmt.Printf("🌐 Hash: %s\n", accountSetResponse.Hash.String())
fmt.Println()
}

// createTrustLine creates a trust line for the holder wallet.
func createTrustLine(client *rpc.Client, issuerWallet, holderWallet, holderWallet2 wallet.Wallet) {
fmt.Println("⏳ Creating trust line for holder wallet...")
trustLine := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: holderWallet.ClassicAddress,
},
LimitAmount: txnTypes.IssuedCurrencyAmount{
Issuer: issuerWallet.ClassicAddress,
Currency: currency.ConvertStringToHex("ABCD"),
Value: "1000000",
},
}
trustLine.SetSetNoRippleFlag()
trustLineResponse, err := client.SubmitTxAndWait(trustLine.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &holderWallet,
})
if err != nil {
fmt.Printf("❌ Error creating trust line: %s\n", err)
return
}
fmt.Println("✅ Trust line created for holder wallet!")
fmt.Printf("🌐 Hash: %s\n", trustLineResponse.Hash.String())
fmt.Println()

fmt.Println("⏳ Creating trust line for holder wallet 2...")
trustLine = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: holderWallet2.ClassicAddress,
},
LimitAmount: txnTypes.IssuedCurrencyAmount{
Issuer: issuerWallet.ClassicAddress,
Currency: currency.ConvertStringToHex("ABCD"),
Value: "1000000",
},
}
trustLine.SetSetNoRippleFlag()
trustLineResponse, err = client.SubmitTxAndWait(trustLine.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &holderWallet2,
})
if err != nil {
fmt.Printf("❌ Error creating trust line: %s\n", err)
return
}
fmt.Println("✅ Trust line created for holder wallet 2!")
fmt.Printf("🌐 Hash: %s\n", trustLineResponse.Hash.String())
fmt.Println()
}

// mintToken mints a token for the holder wallet.
func mintToken(client *rpc.Client, issuerWallet, holderWallet wallet.Wallet) {
fmt.Println("⏳ Minting token to holder wallet...")
token := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: issuerWallet.ClassicAddress,
},
Destination: holderWallet.ClassicAddress,
Amount: txnTypes.IssuedCurrencyAmount{
Issuer: issuerWallet.ClassicAddress,
Currency: currency.ConvertStringToHex("ABCD"),
Value: "10000",
},
}
tokenResponse, err := client.SubmitTxAndWait(token.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &issuerWallet,
})
if err != nil {
fmt.Printf("❌ Error minting token: %s\n", err)
return
}
fmt.Println("✅ Token minted!")
fmt.Printf("🌐 Hash: %s\n", tokenResponse.Hash.String())
fmt.Println()
}

// createEscrow creates an escrow for the holder wallet.
func createEscrow(client *rpc.Client, issuerWallet, holderWallet, holderWallet2 wallet.Wallet) (offerSequence uint32) {
fmt.Println("⏳ Creating escrow...")
escrow := &transactions.EscrowCreate{
BaseTx: transactions.BaseTx{
Account: holderWallet.ClassicAddress,
},
Amount: txnTypes.IssuedCurrencyAmount{
Issuer: issuerWallet.ClassicAddress,
Currency: currency.ConvertStringToHex("ABCD"),
Value: "100",
},
Destination: holderWallet2.ClassicAddress,
CancelAfter: safeInt64ToUint32(rippleTime.UnixTimeToRippleTime(time.Now().Unix()) + 4000),
FinishAfter: safeInt64ToUint32(rippleTime.UnixTimeToRippleTime(time.Now().Unix() + 5)),
}
escrowResponse, err := client.SubmitTxAndWait(escrow.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &holderWallet,
})
if err != nil {
fmt.Printf("❌ Error creating escrow: %s\n", err)
return
}
fmt.Println("✅ Escrow created!")
fmt.Printf("🌐 Hash: %s\n", escrowResponse.Hash.String())
fmt.Printf("🌐 Sequence: %d\n", escrowResponse.TxJSON.Sequence())
fmt.Println()

return escrowResponse.TxJSON.Sequence()

}

// finishEscrow finishes the escrow for the holder wallet 2.
func finishEscrow(client *rpc.Client, holderWallet, holderWallet2 wallet.Wallet, offerSequence uint32) {
fmt.Println("⏳ Finishing escrow...")
escrow := &transactions.EscrowFinish{
BaseTx: transactions.BaseTx{
Account: holderWallet2.ClassicAddress,
},
Owner: holderWallet.ClassicAddress,
OfferSequence: offerSequence,
}
escrowResponse, err := client.SubmitTxAndWait(escrow.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &holderWallet2,
})
if err != nil {
fmt.Printf("❌ Error finishing escrow: %s\n", err)
return
}
fmt.Println("✅ Escrow finished!")
fmt.Printf("🌐 Hash: %s\n", escrowResponse.Hash.String())
fmt.Println()
}
Loading