Skip to content
Merged
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
9 changes: 9 additions & 0 deletions _code-samples/multisigning/js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "multisigning",
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"xrpl": "^4.5.0"
},
"type": "module"
}
92 changes: 92 additions & 0 deletions _code-samples/multisigning/js/set-up-multi-signing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import xrpl from 'xrpl'

const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')
await client.connect()

console.log('Funding new wallet from faucet...')
const { wallet } = await client.fundWallet()
console.log(`Funded. Master key pair:
Address: ${wallet.address}
Seed: ${wallet.seed}
`)

// Generate key pairs to use as signers ----------------------------------------
// If each signer represents a separate person, they should generate their own
// key pairs and send you just the address. These key pairs don't need to be
// funded accounts in the ledger.
const algorithm = 'ed25519'
const signerAddresses = []
for (let i = 0; i < 3; i++) {
const signer = xrpl.Wallet.generate(algorithm)
console.log(`Generated key pair for signer ${i + 1}:
Address: ${signer.address}
Seed: ${signer.seed}
Algorithm: ${algorithm}
`)
signerAddresses.push(signer.address)
}

// Send SignerListSet transaction ----------------------------------------------
// This example sets up a 2-of-3 requirement with all signers weighted equally
const signerEntries = []
for (const signerAddress of signerAddresses) {
signerEntries.push({
SignerEntry: {
Account: signerAddress,
SignerWeight: 1
}
})
}
const signerListSetTx = {
TransactionType: 'SignerListSet',
Account: wallet.address,
SignerQuorum: 2,
SignerEntries: signerEntries
}
xrpl.validate(signerListSetTx)

console.log('Signing and submitting the SignerListSet transaction:',
JSON.stringify(signerListSetTx, null, 2))
const response = await client.submitAndWait(signerListSetTx, { wallet, autofill: true })

// Check result of the SignerListSet transaction -------------------------------
console.log(JSON.stringify(response.result, null, 2))
const listSetResultCode = response.result.meta.TransactionResult
if (listSetResultCode === 'tesSUCCESS') {
console.log('Signer list set successfully.')
} else {
console.error(`SignerListSet failed with code ${listSetResultCode}.`)
client.disconnect()
process.exit(1)
}

// Confirm signer list ---------------------------------------------------------
const accountInfoResp = await client.request({
command: 'account_info',
account: wallet.address,
ledger_index: 'validated',
signer_lists: true
})
if (accountInfoResp.error) {
console.error('Error looking up account:', accountInfoResp.error)
client.disconnect()
process.exit(1)
}

if (accountInfoResp.result.signer_lists) {
const lists = accountInfoResp.result.signer_lists
console.log(`Account has ${lists.length} signer list(s):`)
for (const l of lists) {
console.log(` List #${l.SignerListID} Quorum = ${l.SignerQuorum}`)
for (const SEWrapper of l.SignerEntries) {
const se = SEWrapper.SignerEntry
console.log(` Signer ${se.Account} Weight = ${se.SignerWeight}`)
}
}
} else {
console.error(`No signer lists associated with ${wallet.address}`)
client.disconnect()
process.exit(1)
}

client.disconnect()
1 change: 1 addition & 0 deletions _code-samples/multisigning/py/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xrpl-py>=4.4.0
84 changes: 84 additions & 0 deletions _code-samples/multisigning/py/set-up-multi-signing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import json
from xrpl.clients import JsonRpcClient
from xrpl.models.requests import AccountInfo
from xrpl.models.transactions import SignerEntry, SignerListSet
from xrpl.wallet import generate_faucet_wallet, Wallet
from xrpl.transaction import submit_and_wait

client = JsonRpcClient("https://s.altnet.rippletest.net:51234")

print("Funding new wallet from faucet...")
wallet = generate_faucet_wallet(client)
print(f"""Funded. Master key pair:
Address: {wallet.address}
Seed: {wallet.seed}
""")

# Generate key pairs to use as signers -----------------------------------------
# If each signer represents a separate person, they should generate their own
# key pairs and send you just the address. These key pairs don't need to be
# funded accounts in the ledger.
algorithm = "ed25519"
signer_addresses = []
for i in range(3):
signer = Wallet.create(algorithm=algorithm)
print(f"""Generated key pair for signer {i + 1}:
Address: {signer.address}
Seed: {signer.seed}
Algorithm: {algorithm}
""")
signer_addresses.append(signer.address)

# Send SignerListSet transaction -----------------------------------------------
# This example sets up a 2-of-3 requirement with all signers weighted equally
signer_list_set_tx = SignerListSet(
account=wallet.address,
signer_quorum=2,
signer_entries=[
SignerEntry(account=signer_address, signer_weight=1)
for signer_address in signer_addresses
],
)

print(
"Signing and submitting the SignerListSet transaction:",
json.dumps(signer_list_set_tx.to_xrpl(), indent=2),
)
try:
response = submit_and_wait(signer_list_set_tx, client, wallet)
except Exception as err:
print("Submitting SignerListSet transaction failed with error", err)
exit(1)

# Check result of the SignerListSet transaction --------------------------------
print(json.dumps(response.result, indent=2))
signer_list_set_result_code = response.result["meta"]["TransactionResult"]
if signer_list_set_result_code == "tesSUCCESS":
print("Signer list set successfully.")
else:
print(f"SignerListSet failed with code {signer_list_set_result_code}.")
exit(1)

# Confirm signer list ----------------------------------------------------------
try:
account_info_resp = client.request(
AccountInfo(account=wallet.address, ledger_index="validated", signer_lists=True)
)
except Exception as err:
print("Error requesting account_info:", err)
exit(1)
if not account_info_resp.is_successful():
print("Error looking up account:", account_info_resp.result)
exit(1)

if account_info_resp.result.get("signer_lists"):
lists = account_info_resp.result["signer_lists"]
print(f"Account has {len(lists)} signer list(s):")
for l in lists:
print(f" List #{l['SignerListID']} Quorum = {l['SignerQuorum']}")
for se_wrapper in l["SignerEntries"]:
se = se_wrapper["SignerEntry"]
print(f" Signer {se['Account']} Weight = {se['SignerWeight']}")
else:
print(f"No signer lists associated with {wallet.address}")
exit(1)
Loading